1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Decoupled all module logic from their viewmodels

Added GTA V support
This commit is contained in:
SpoinkyNL 2016-11-09 00:06:01 +01:00
parent 065940c1f9
commit 2d9a656dde
64 changed files with 1044 additions and 691 deletions

View File

@ -11,6 +11,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnrealTournament2Artemis",
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorBox", "ColorBox\ColorBox.csproj", "{40085232-ACED-4CBE-945B-90BA8153C151}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorBox", "ColorBox\ColorBox.csproj", "{40085232-ACED-4CBE-945B-90BA8153C151}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LogiLed2Artemis", "LogiLed2Artemis\LogiLed2Artemis.vcxproj", "{D2EDB8F3-F0CB-4670-B472-0B46D5800D2C}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
CD_ROM|Any CPU = CD_ROM|Any CPU 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|x64.Build.0 = Release|Any CPU
{40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.ActiveCfg = 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 {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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -367,6 +367,13 @@
<DependentUpon>EurotruckSimulator2View.xaml</DependentUpon> <DependentUpon>EurotruckSimulator2View.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Modules\Games\EurotruckSimulator2\EurotruckSimulator2ViewModel.cs" /> <Compile Include="Modules\Games\EurotruckSimulator2\EurotruckSimulator2ViewModel.cs" />
<Compile Include="Modules\Games\GtaV\GtaVDataModel.cs" />
<Compile Include="Modules\Games\GtaV\GtaVModel.cs" />
<Compile Include="Modules\Games\GtaV\GtaVSettings.cs" />
<Compile Include="Modules\Games\GtaV\GtaVView.xaml.cs">
<DependentUpon>GtaVView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\Games\GtaV\GtaVViewModel.cs" />
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentDataModel.cs" /> <Compile Include="Modules\Games\UnrealTournament\UnrealTournamentDataModel.cs" />
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentModel.cs" /> <Compile Include="Modules\Games\UnrealTournament\UnrealTournamentModel.cs" />
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentSettings.cs" /> <Compile Include="Modules\Games\UnrealTournament\UnrealTournamentSettings.cs" />
@ -763,6 +770,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Modules\Games\GtaV\GtaVView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Modules\Games\Overwatch\OverwatchView.xaml"> <Page Include="Modules\Games\Overwatch\OverwatchView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>

View File

@ -1,9 +1,10 @@
using Artemis.Modules.Effects.ProfilePreview; using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Services; using Artemis.Services;
using Artemis.Utilities.DataReaders;
using Artemis.Utilities.GameState;
using Artemis.ViewModels; using Artemis.ViewModels;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
using Ninject.Modules; using Ninject.Modules;
namespace Artemis.InjectionModules namespace Artemis.InjectionModules
@ -13,15 +14,15 @@ namespace Artemis.InjectionModules
public override void Load() public override void Load()
{ {
// ViewModels // ViewModels
Bind<IScreen>().To<ShellViewModel>().InSingletonScope(); Bind<ShellViewModel>().ToSelf();
Bind<ProfileViewModel>().ToSelf(); Bind<ProfileViewModel>().ToSelf();
Bind<ProfileEditorViewModel>().ToSelf(); Bind<ProfileEditorViewModel>().ToSelf();
Bind<DebugViewModel>().ToSelf().InSingletonScope(); Bind<DebugViewModel>().ToSelf().InSingletonScope();
Bind<BaseViewModel>().To<WelcomeViewModel>().InSingletonScope(); Bind<BaseViewModel>().To<WelcomeViewModel>();
Bind<BaseViewModel>().To<EffectsViewModel>().InSingletonScope(); Bind<BaseViewModel>().To<EffectsViewModel>();
Bind<BaseViewModel>().To<GamesViewModel>().InSingletonScope(); Bind<BaseViewModel>().To<GamesViewModel>();
Bind<BaseViewModel>().To<OverlaysViewModel>().InSingletonScope(); Bind<BaseViewModel>().To<OverlaysViewModel>();
// Models // Models
Bind<ProfilePreviewModel>().ToSelf().InSingletonScope(); Bind<ProfilePreviewModel>().ToSelf().InSingletonScope();
@ -29,6 +30,10 @@ namespace Artemis.InjectionModules
// Services // Services
Bind<MetroDialogService>().ToSelf().InSingletonScope(); Bind<MetroDialogService>().ToSelf().InSingletonScope();
Bind<WindowService>().ToSelf().InSingletonScope(); Bind<WindowService>().ToSelf().InSingletonScope();
// Servers
Bind<GameStateWebServer>().ToSelf().InSingletonScope();
Bind<PipeServer>().ToSelf().InSingletonScope();
} }
} }
} }

View File

@ -16,26 +16,16 @@ namespace Artemis.InjectionModules
.SelectAllClasses() .SelectAllClasses()
.InheritedFrom<EffectModel>() .InheritedFrom<EffectModel>()
.BindBase() .BindBase()
.Configure(b => b.InSingletonScope()); .Configure((b, c) => b.InSingletonScope().Named(c.Name));
}); });
// View models
Kernel.Bind(x => Kernel.Bind(x =>
{ {
x.FromThisAssembly() x.FromThisAssembly()
.SelectAllClasses() .SelectAllClasses()
.InheritedFrom<EffectViewModel>() .InheritedFrom<EffectViewModel>()
.BindBase() .BindBase();
.Configure(b => b.InSingletonScope());
});
// Games
Kernel.Bind(x =>
{
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<GameModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
}); });
Kernel.Bind(x => Kernel.Bind(x =>
@ -43,27 +33,14 @@ namespace Artemis.InjectionModules
x.FromThisAssembly() x.FromThisAssembly()
.SelectAllClasses() .SelectAllClasses()
.InheritedFrom<GameViewModel>() .InheritedFrom<GameViewModel>()
.BindBase() .BindBase();
.Configure(b => b.InSingletonScope());
}); });
// Overlays
Kernel.Bind(x =>
{
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<OverlayModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
});
Kernel.Bind(x => Kernel.Bind(x =>
{ {
x.FromThisAssembly() x.FromThisAssembly()
.SelectAllClasses() .SelectAllClasses()
.InheritedFrom<OverlayViewModel>() .InheritedFrom<OverlayViewModel>()
.BindBase() .BindBase();
.Configure(b => b.InSingletonScope());
}); });
} }
} }

View File

@ -21,14 +21,24 @@ namespace Artemis.Managers
private EffectModel _waitEffect; private EffectModel _waitEffect;
private readonly GeneralSettings _generalSettings; private readonly GeneralSettings _generalSettings;
public EffectManager(ILogger logger, DeviceManager deviceManager) public EffectManager(ILogger logger, DeviceManager deviceManager, List<EffectModel> effectModels,
List<GameModel> gameModels, List<OverlayModel> overlayModels)
{ {
EffectModels = new List<EffectModel>();
_generalSettings = DAL.SettingsProvider.Load<GeneralSettings>(); _generalSettings = DAL.SettingsProvider.Load<GeneralSettings>();
_logger = logger; _logger = logger;
_deviceManager = deviceManager; _deviceManager = deviceManager;
var models = new List<EffectModel>();
// 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"); _logger.Info("Intialized EffectManager");
} }

View File

@ -23,7 +23,8 @@ namespace Artemis.Managers
private readonly Timer _processTimer; private readonly Timer _processTimer;
public MainManager(ILogger logger, LoopManager loopManager, DeviceManager deviceManager, public MainManager(ILogger logger, LoopManager loopManager, DeviceManager deviceManager,
EffectManager effectManager, ProfileManager profileManager, PipeServer pipeServer) EffectManager effectManager, ProfileManager profileManager, PipeServer pipeServer,
GameStateWebServer gameStateWebServer)
{ {
Logger = logger; Logger = logger;
LoopManager = loopManager; LoopManager = loopManager;
@ -40,7 +41,7 @@ namespace Artemis.Managers
Running = false; Running = false;
// Create and start the web server // Create and start the web server
GameStateWebServer = new GameStateWebServer(logger); GameStateWebServer = gameStateWebServer;
GameStateWebServer.Start(); GameStateWebServer.Start();
// Start the named pipe // Start the named pipe

View File

@ -3,14 +3,17 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using Artemis.DAL;
using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models.Interfaces; using Artemis.Models.Interfaces;
using Artemis.Profiles; using Artemis.Profiles;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Lua;
using Artemis.Settings; using Artemis.Settings;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ninject;
using Ninject.Extensions.Logging;
namespace Artemis.Models namespace Artemis.Models
{ {
@ -20,25 +23,37 @@ namespace Artemis.Models
protected DateTime LastTrace; 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; Settings = settings;
DataModel = dataModel; 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 bool Initialized { get; set; }
public MainManager MainManager { get; set; } public DeviceManager DeviceManager { get; set; }
public EffectSettings Settings { get; set; } public EffectSettings Settings { get; set; }
public string Name { get; set; } public string Name { get; set; }
public int KeyboardScale { get; set; } = 4; public int KeyboardScale { get; set; } = 4;
// Used by profile system // Used by profile system
public IDataModel DataModel { get; set; } public IDataModel DataModel { get; set; }
public ProfileModel Profile { get; set; } public ProfileModel Profile { get; set; }
[Inject]
public ILogger Logger { get; set; }
public virtual void Dispose() public virtual void Dispose()
{ {
Profile?.Deactivate(); Profile?.Deactivate();
@ -58,7 +73,7 @@ namespace Artemis.Models
/// <param name="keyboardOnly"></param> /// <param name="keyboardOnly"></param>
public virtual void Render(RenderFrame frame, bool keyboardOnly) 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; return;
lock (DataModel) lock (DataModel)
@ -68,10 +83,10 @@ namespace Artemis.Models
// If the profile has no active LUA wrapper, create one // If the profile has no active LUA wrapper, create one
if (!string.IsNullOrEmpty(Profile.LuaScript)) if (!string.IsNullOrEmpty(Profile.LuaScript))
Profile.Activate(MainManager.DeviceManager.ActiveKeyboard); Profile.Activate(DeviceManager.ActiveKeyboard);
// Render the keyboard layer-by-layer // 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)) using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
@ -104,15 +119,15 @@ namespace Artemis.Models
} }
// Trace debugging // Trace debugging
if (DateTime.Now.AddSeconds(-2) <= LastTrace) if (DateTime.Now.AddSeconds(-2) <= LastTrace || Logger == null)
return; return;
LastTrace = DateTime.Now; LastTrace = DateTime.Now;
MainManager.Logger.Trace("Effect datamodel as JSON: \r\n{0}", var dmJson = JsonConvert.SerializeObject(DataModel, Formatting.Indented);
JsonConvert.SerializeObject(DataModel, Formatting.Indented)); Logger.Trace("Effect datamodel as JSON: \r\n{0}", dmJson);
MainManager.Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count); Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count);
foreach (var renderLayer in renderLayers) foreach (var renderLayer in renderLayers)
MainManager.Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType);
renderLayer.LayerType);
} }
} }

View File

@ -6,7 +6,7 @@ namespace Artemis.Models
{ {
public abstract class GameModel : EffectModel 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 // Override settings to the GameSettings type
Settings = settings; Settings = settings;

View File

@ -8,7 +8,7 @@ namespace Artemis.Models
private bool _enabled; private bool _enabled;
public string ProcessName; 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; Settings = settings;
Enabled = settings.Enabled; Enabled = settings.Enabled;

View File

@ -1,12 +1,14 @@
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.ProfilePreview; using Artemis.Modules.Effects.ProfilePreview;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Effects.AudioVisualizer namespace Artemis.Modules.Effects.AudioVisualizer
{ {
public sealed class AudioVisualizerViewModel : EffectViewModel 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"; DisplayName = "Audio Visualization / Key waves";
} }

View File

@ -15,7 +15,7 @@ namespace Artemis.Modules.Effects.Bubbles
{ {
#region Constructors #region Constructors
public BubblesModel(MainManager mainManager) : base(mainManager, SettingsProvider.Load<BubblesSettings>(), null) public BubblesModel(DeviceManager deviceManager) : base(deviceManager, SettingsProvider.Load<BubblesSettings>(), null)
{ {
Name = "Bubbles"; Name = "Bubbles";
Initialized = false; Initialized = false;
@ -40,8 +40,7 @@ namespace Artemis.Modules.Effects.Bubbles
{ {
KeyboardScale = Settings.Smoothness; KeyboardScale = Settings.Smoothness;
var rect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); var rect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
var scaleFactor = Settings.Smoothness/25.0; var scaleFactor = Settings.Smoothness/25.0;
for (var i = 0; i < Settings.BubbleCount; i++) for (var i = 0; i < Settings.BubbleCount; i++)
@ -74,7 +73,7 @@ namespace Artemis.Modules.Effects.Bubbles
public override void Update() public override void Update()
{ {
var keyboardRectangle = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); var keyboardRectangle = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
foreach (var bubble in _bubbles) foreach (var bubble in _bubbles)
{ {
if (Settings.IsShiftColors) if (Settings.IsShiftColors)

View File

@ -1,6 +1,8 @@
using System.Windows.Media; using System.Windows.Media;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Effects.Bubbles namespace Artemis.Modules.Effects.Bubbles
{ {
@ -9,11 +11,11 @@ namespace Artemis.Modules.Effects.Bubbles
private readonly BubblesModel _model; private readonly BubblesModel _model;
private SolidColorBrush _bubbleColor; 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"; DisplayName = "Bubbles";
BubbleColor = new SolidColorBrush(model.Settings.BubbleColor); BubbleColor = new SolidColorBrush(_model.Settings.BubbleColor);
} }
/// <summary> /// <summary>

View File

@ -16,7 +16,8 @@ namespace Artemis.Modules.Effects.ProfilePreview
{ {
public class ProfilePreviewModel : EffectModel 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"; Name = "Profile Preview";
} }
@ -45,7 +46,7 @@ namespace Artemis.Modules.Effects.ProfilePreview
public override void Render(RenderFrame frame, bool keyboardOnly) 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; return;
lock (DataModel) lock (DataModel)
@ -54,11 +55,11 @@ namespace Artemis.Modules.Effects.ProfilePreview
var renderLayers = GetRenderLayers(keyboardOnly); var renderLayers = GetRenderLayers(keyboardOnly);
// If the profile has no active LUA wrapper, create one // If the profile has no active LUA wrapper, create one
if (!string.IsNullOrEmpty(Profile.LuaScript)) if (!Equals(LuaWrapper.ProfileModel, Profile))
Profile.Activate(MainManager.DeviceManager.ActiveKeyboard); Profile.Activate(DeviceManager.ActiveKeyboard);
// Render the keyboard layer-by-layer // 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)) using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{ {
Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),

View File

@ -9,25 +9,22 @@ using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ninject.Extensions.Logging;
using SpotifyAPI.Local; using SpotifyAPI.Local;
namespace Artemis.Modules.Effects.WindowsProfile namespace Artemis.Modules.Effects.WindowsProfile
{ {
public class WindowsProfileModel : EffectModel public class WindowsProfileModel : EffectModel
{ {
private readonly ILogger _logger;
private List<PerformanceCounter> _cores; private List<PerformanceCounter> _cores;
private int _cpuFrames; private int _cpuFrames;
private DateTime _lastMusicUpdate;
private PerformanceCounter _overallCpu; private PerformanceCounter _overallCpu;
private SpotifyLocalAPI _spotify; private SpotifyLocalAPI _spotify;
private bool _spotifySetupBusy; private bool _spotifySetupBusy;
private DateTime _lastMusicUpdate;
public WindowsProfileModel(ILogger logger, MainManager mainManager) public WindowsProfileModel(DeviceManager deviceManager)
: base(mainManager, SettingsProvider.Load<WindowsProfileSettings>(), new WindowsProfileDataModel()) : base(deviceManager, SettingsProvider.Load<WindowsProfileSettings>(), new WindowsProfileDataModel())
{ {
_logger = logger;
_lastMusicUpdate = DateTime.Now; _lastMusicUpdate = DateTime.Now;
Name = "WindowsProfile"; Name = "WindowsProfile";
@ -85,7 +82,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
} }
catch (InvalidOperationException) 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) if (dataModel.Spotify.SongLength > 0)
{
dataModel.Spotify.SongPercentCompleted = dataModel.Spotify.SongPercentCompleted =
(int) (status.PlayingPosition/dataModel.Spotify.SongLength*100.0); (int) (status.PlayingPosition/dataModel.Spotify.SongLength*100.0);
}
} }
private void UpdateGooglePlayMusic(WindowsProfileDataModel dataModel) private void UpdateGooglePlayMusic(WindowsProfileDataModel dataModel)

View File

@ -1,5 +1,6 @@
using System.ComponentModel; using System.ComponentModel;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.ProfilePreview; using Artemis.Modules.Effects.ProfilePreview;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
@ -12,7 +13,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
public sealed class WindowsProfileViewModel : EffectViewModel public sealed class WindowsProfileViewModel : EffectViewModel
{ {
public WindowsProfileViewModel(MainManager main, IKernel kernel, ProfilePreviewModel profilePreviewModel, public WindowsProfileViewModel(MainManager main, IKernel kernel, ProfilePreviewModel profilePreviewModel,
WindowsProfileModel model) : base(main, model) [Named("WindowsProfileModel")] EffectModel model) : base(main, model)
{ {
DisplayName = "Windows Profile"; DisplayName = "Windows Profile";
ProfilePreviewModel = profilePreviewModel; ProfilePreviewModel = profilePreviewModel;
@ -25,10 +26,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
new ConstructorArgument("lastProfile", ((WindowsProfileSettings) EffectSettings).LastProfile) new ConstructorArgument("lastProfile", ((WindowsProfileSettings) EffectSettings).LastProfile)
}; };
ProfileEditor = kernel.Get<ProfileEditorViewModel>(args); ProfileEditor = kernel.Get<ProfileEditorViewModel>(args);
ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile;
ProfileEditor.PropertyChanged += ProfileUpdater; ProfileEditor.PropertyChanged += ProfileUpdater;
MainManager.EffectManager.EffectModels.Add(EffectModel);
} }
public ProfileEditorViewModel ProfileEditor { get; set; } public ProfileEditorViewModel ProfileEditor { get; set; }
@ -44,6 +42,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
if ((e.PropertyName != "SelectedProfile") || !ProfileEditor.ProfileViewModel.Activated || if ((e.PropertyName != "SelectedProfile") || !ProfileEditor.ProfileViewModel.Activated ||
(ProfileEditor.ProfileViewModel.SelectedProfile == null)) (ProfileEditor.ProfileViewModel.SelectedProfile == null))
return; return;
((WindowsProfileSettings) EffectSettings).LastProfile = ProfileEditor.ProfileViewModel.SelectedProfile.Name; ((WindowsProfileSettings) EffectSettings).LastProfile = ProfileEditor.ProfileViewModel.SelectedProfile.Name;
EffectSettings.Save(); EffectSettings.Save();
} }

View File

@ -1,48 +1,57 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.GameState; using Artemis.Utilities.GameState;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ninject.Extensions.Logging;
namespace Artemis.Modules.Games.CounterStrike namespace Artemis.Modules.Games.CounterStrike
{ {
public class CounterStrikeModel : GameModel public class CounterStrikeModel : GameModel
{ {
private readonly MetroDialogService _dialogService;
private readonly GameStateWebServer _gameStateWebServer;
private DateTime _lastHeadshot; private DateTime _lastHeadshot;
private int _lastHeadshots; private int _lastHeadshots;
private DateTime _lastKill; private DateTime _lastKill;
private int _lastKills; private int _lastKills;
public CounterStrikeModel(MainManager mainManager) public CounterStrikeModel(DeviceManager deviceManager, GameStateWebServer gameStateWebServer,
: base(mainManager, SettingsProvider.Load<CounterStrikeSettings>(), new CounterStrikeDataModel()) MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<CounterStrikeSettings>(), new CounterStrikeDataModel())
{ {
_gameStateWebServer = gameStateWebServer;
_dialogService = dialogService;
Name = "CounterStrike"; Name = "CounterStrike";
ProcessName = "csgo"; ProcessName = "csgo";
Scale = 4; Scale = 4;
Enabled = Settings.Enabled; Enabled = Settings.Enabled;
Initialized = false; Initialized = false;
FindGameDir();
PlaceConfigFile();
} }
public ILogger Logger { get; set; }
public int Scale { get; set; } public int Scale { get; set; }
public override void Dispose() public override void Dispose()
{ {
Initialized = false; Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData; _gameStateWebServer.GameDataReceived -= HandleGameData;
base.Dispose(); base.Dispose();
} }
public override void Enable() public override void Enable()
{ {
Initialized = false; _gameStateWebServer.GameDataReceived += HandleGameData;
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true; Initialized = true;
} }
@ -90,6 +99,42 @@ namespace Artemis.Modules.Games.CounterStrike
DataModel = dm; 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) public void HandleGameData(object sender, GameDataReceivedEventArgs e)
{ {
var jsonString = e.Json.ToString(); var jsonString = e.Json.ToString();
@ -112,6 +157,7 @@ namespace Artemis.Modules.Games.CounterStrike
} }
} }
public override List<LayerModel> GetRenderLayers(bool keyboardOnly) public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{ {
return Profile.GetRenderLayers(DataModel, keyboardOnly); return Profile.GetRenderLayers(DataModel, keyboardOnly);

View File

@ -1,72 +1,22 @@
using System.IO; using Artemis.Managers;
using System.Windows.Forms; using Artemis.Models;
using Ninject;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.CounterStrike namespace Artemis.Modules.Games.CounterStrike
{ {
public sealed class CounterStrikeViewModel : GameViewModel 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) : base(main, model, kernel)
{ {
DisplayName = "CS:GO"; 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() public void BrowseDirectory()
{ {
var dialog = new FolderBrowserDialog {SelectedPath = ((CounterStrikeSettings) GameSettings).GameDirectory}; ((CounterStrikeModel) GameModel).PlaceConfigFile();
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
((CounterStrikeSettings) GameSettings).GameDirectory = Path.GetDirectoryName(dialog.SelectedPath);
NotifyOfPropertyChange(() => GameSettings); 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();
} }
} }
} }

View File

@ -1,8 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.GameState; using Artemis.Utilities.GameState;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -10,14 +14,24 @@ namespace Artemis.Modules.Games.Dota2
{ {
public class Dota2Model : GameModel public class Dota2Model : GameModel
{ {
public Dota2Model(MainManager mainManager) private readonly MetroDialogService _dialogService;
: base(mainManager, SettingsProvider.Load<Dota2Settings>(), new Dota2DataModel()) private readonly GameStateWebServer _gameStateWebServer;
public Dota2Model(DeviceManager deviceManager, GameStateWebServer gameStateWebServer,
MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<Dota2Settings>(), new Dota2DataModel())
{ {
_gameStateWebServer = gameStateWebServer;
_dialogService = dialogService;
Name = "Dota2"; Name = "Dota2";
ProcessName = "dota2"; ProcessName = "dota2";
Enabled = Settings.Enabled; Enabled = Settings.Enabled;
Initialized = false; Initialized = false;
Scale = 4; Scale = 4;
FindGameDir();
PlaceConfigFile();
} }
public int Scale { get; set; } public int Scale { get; set; }
@ -25,13 +39,13 @@ namespace Artemis.Modules.Games.Dota2
public override void Dispose() public override void Dispose()
{ {
Initialized = false; Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData; _gameStateWebServer.GameDataReceived -= HandleGameData;
base.Dispose(); base.Dispose();
} }
public override void Enable() public override void Enable()
{ {
MainManager.GameStateWebServer.GameDataReceived += HandleGameData; _gameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true; Initialized = true;
} }
@ -40,6 +54,55 @@ namespace Artemis.Modules.Games.Dota2
UpdateDay(); 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() private void UpdateDay()
{ {
var dataModel = DataModel as Dota2DataModel; var dataModel = DataModel as Dota2DataModel;

View File

@ -1,88 +1,22 @@
using System.IO; using Artemis.Managers;
using System.Windows.Forms; using Artemis.Models;
using Ninject;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.Dota2 namespace Artemis.Modules.Games.Dota2
{ {
public sealed class Dota2ViewModel : GameViewModel 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) : base(main, model, kernel)
{ {
DisplayName = "Dota 2"; 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() public void PlaceConfigFile()
{ {
if (((Dota2Settings) GameSettings).GameDirectory == string.Empty) ((Dota2Model) GameModel).PlaceConfigFile();
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;
NotifyOfPropertyChange(() => GameSettings); NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
} }
} }
} }

View File

@ -1,27 +1,37 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.IO;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Modules.Games.EurotruckSimulator2.Data; using Artemis.Modules.Games.EurotruckSimulator2.Data;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
namespace Artemis.Modules.Games.EurotruckSimulator2 namespace Artemis.Modules.Games.EurotruckSimulator2
{ {
public class EurotruckSimulator2Model : GameModel public class EurotruckSimulator2Model : GameModel
{ {
public EurotruckSimulator2Model(MainManager mainManager) private readonly MetroDialogService _dialogService;
: base(mainManager, SettingsProvider.Load<EurotruckSimulator2Settings>(), new EurotruckSimulator2DataModel()
) public EurotruckSimulator2Model(DeviceManager deviceManager, MetroDialogService dialogService)
: base(
deviceManager, SettingsProvider.Load<EurotruckSimulator2Settings>(), new EurotruckSimulator2DataModel())
{ {
_dialogService = dialogService;
Name = "EurotruckSimulator2"; Name = "EurotruckSimulator2";
ProcessName = "eurotrucks2"; ProcessName = "eurotrucks2";
Scale = 4; Scale = 4;
Enabled = Settings.Enabled; Enabled = Settings.Enabled;
Initialized = false; Initialized = false;
FindGameDir();
} }
public ILogger Logger { get; set; }
public int Scale { get; set; } public int Scale { get; set; }
public override void Dispose() public override void Dispose()
@ -47,6 +57,66 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
dataModel.Truck = telemetryData.Truck; 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<LayerModel> GetRenderLayers(bool keyboardOnly) public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{ {
return Profile.GetRenderLayers(DataModel, keyboardOnly); return Profile.GetRenderLayers(DataModel, keyboardOnly);

View File

@ -1,40 +1,18 @@
using System; using System.IO;
using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using Ninject;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Properties; using Artemis.Models;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.EurotruckSimulator2 namespace Artemis.Modules.Games.EurotruckSimulator2
{ {
public sealed class EurotruckSimulator2ViewModel : GameViewModel public sealed class EurotruckSimulator2ViewModel : GameViewModel
{ {
public EurotruckSimulator2ViewModel(MainManager main, IKernel kernel, public EurotruckSimulator2ViewModel(MainManager main, IKernel kernel,
EurotruckSimulator2Model model) : base(main, model, kernel) [Named("EurotruckSimulator2Model")] GameModel model) : base(main, model, kernel)
{ {
DisplayName = "ETS 2"; 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() public void BrowseDirectory()
@ -51,49 +29,7 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
NotifyOfPropertyChange(() => GameSettings); NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save(); GameSettings.Save();
PlacePlugin(); ((EurotruckSimulator2Model) GameModel).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;
}
} }
} }
} }

View File

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

View File

@ -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<GtaVSettings>(), 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<LayerModel> 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();
}
}
}

View File

@ -0,0 +1,8 @@
using Artemis.Settings;
namespace Artemis.Modules.Games.GtaV
{
public class GtaVSettings : GameSettings
{
}
}

View File

@ -0,0 +1,54 @@
<UserControl x:Class="Artemis.Modules.Games.GtaV.GtaVView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid Margin="15, 5, 15, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap"
Text="By default fills up the keyboard and colors all devices according to the character you're playing/team you're in." />
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable effect" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton x:Name="EffectEnabled" Margin="0 3 0 0" Width="25" Height="25"
IsChecked="{Binding Path=GameSettings.Enabled, Mode=TwoWay}"
Style="{DynamicResource MetroCircleToggleButtonStyle}"
cal:Message.Attach="[Event Click] = [Action ToggleEffect]" />
</StackPanel>
</StackPanel>
<!-- Profile editor -->
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="9" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"
Margin="10,0,0,0"
Style="{DynamicResource SquareButtonStyle}" />
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>

View File

@ -0,0 +1,15 @@
using System.Windows.Controls;
namespace Artemis.Modules.Games.GtaV
{
/// <summary>
/// Interaction logic for GtaVView.xaml
/// </summary>
public partial class GtaVView : UserControl
{
public GtaVView()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,16 @@
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.GtaV
{
public sealed class GtaVViewModel : GameViewModel
{
public GtaVViewModel(MainManager mainManager, [Named("GtaVModel")] GameModel model, IKernel kernel)
: base(mainManager, model, kernel)
{
DisplayName = "GTA V";
}
}
}

View File

@ -1,19 +1,23 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Windows.Media; using System.Windows.Media;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Settings; using Artemis.Services;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.DataReaders;
using Microsoft.Win32;
namespace Artemis.Modules.Games.Overwatch namespace Artemis.Modules.Games.Overwatch
{ {
public class OverwatchModel : GameModel public class OverwatchModel : GameModel
{ {
private readonly PipeServer _pipeServer;
private readonly MetroDialogService _dialogService;
private DateTime _characterChange; private DateTime _characterChange;
private string _lastMessage; private string _lastMessage;
// Using sticky values on these since they can cause flickering // Using sticky values on these since they can cause flickering
@ -23,9 +27,11 @@ namespace Artemis.Modules.Games.Overwatch
private DateTime _ultimateReady; private DateTime _ultimateReady;
private DateTime _ultimateUsed; private DateTime _ultimateUsed;
public OverwatchModel(MainManager mainManager) public OverwatchModel(DeviceManager deviceManager, PipeServer pipeServer, MetroDialogService dialogService)
: base(mainManager, SettingsProvider.Load<OverwatchSettings>(), new OverwatchDataModel()) : base(deviceManager, SettingsProvider.Load<OverwatchSettings>(), new OverwatchDataModel())
{ {
_pipeServer = pipeServer;
_dialogService = dialogService;
Name = "Overwatch"; Name = "Overwatch";
ProcessName = "Overwatch"; ProcessName = "Overwatch";
Scale = 4; Scale = 4;
@ -33,11 +39,7 @@ namespace Artemis.Modules.Games.Overwatch
Initialized = false; Initialized = false;
LoadOverwatchCharacters(); LoadOverwatchCharacters();
} FindOverwatch();
public OverwatchModel(MainManager mainManager, GameSettings settings, IDataModel dataModel)
: base(mainManager, settings, dataModel)
{
} }
public List<CharacterColor> OverwatchCharacters { get; set; } public List<CharacterColor> OverwatchCharacters { get; set; }
@ -77,7 +79,7 @@ namespace Artemis.Modules.Games.Overwatch
_stickyStatus = new StickyValue<OverwatchStatus>(300); _stickyStatus = new StickyValue<OverwatchStatus>(300);
_stickyUltimateReady = new StickyValue<bool>(350); _stickyUltimateReady = new StickyValue<bool>(350);
_stickyUltimateUsed = new StickyValue<bool>(350); _stickyUltimateUsed = new StickyValue<bool>(350);
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage; _pipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true; Initialized = true;
} }
@ -90,7 +92,7 @@ namespace Artemis.Modules.Games.Overwatch
_stickyUltimateReady.Dispose(); _stickyUltimateReady.Dispose();
_stickyUltimateUsed.Dispose(); _stickyUltimateUsed.Dispose();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage; _pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose(); base.Dispose();
} }
@ -177,7 +179,7 @@ namespace Artemis.Modules.Games.Overwatch
} }
catch (FormatException e) catch (FormatException e)
{ {
MainManager.Logger.Trace(e, "Failed to parse to color array"); Logger?.Trace(e, "Failed to parse to color array");
return null; return null;
} }
} }
@ -271,6 +273,46 @@ namespace Artemis.Modules.Games.Overwatch
{ {
return Profile.GetRenderLayers(DataModel, keyboardOnly); return Profile.GetRenderLayers(DataModel, keyboardOnly);
} }
public void FindOverwatch()
{
var gameSettings = (OverwatchSettings) Settings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "Overwatch.exe") &&
File.Exists(gameSettings.GameDirectory + "RzChromaSDK64.dll"))
return;
var key = Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Overwatch");
if (key == null)
return;
var path = key.GetValue("DisplayIcon").ToString();
if (!File.Exists(path))
return;
gameSettings.GameDirectory = path.Substring(0, path.Length - 14);
gameSettings.Save();
PlaceDll();
}
public void PlaceDll()
{
var settings = (OverwatchSettings) Settings;
var path = settings.GameDirectory;
if (!File.Exists(path + @"\Overwatch.exe"))
{
_dialogService.ShowErrorMessageBox("Please select a valid Overwatch directory\n\n" +
@"By default Overwatch is in C:\Program Files (x86)\Overwatch");
settings.GameDirectory = string.Empty;
settings.Save();
return;
}
DllManager.PlaceRazerDll(path);
}
} }
public struct CharacterColor public struct CharacterColor

View File

@ -1,43 +1,17 @@
using System.IO; using System.Windows.Forms;
using System.Windows.Forms;
using Ninject;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Utilities.DataReaders; using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Microsoft.Win32; using Ninject;
namespace Artemis.Modules.Games.Overwatch namespace Artemis.Modules.Games.Overwatch
{ {
public sealed class OverwatchViewModel : GameViewModel public sealed class OverwatchViewModel : GameViewModel
{ {
public OverwatchViewModel(MainManager main, IKernel kernel, OverwatchModel model) public OverwatchViewModel(MainManager main, IKernel kernel, [Named("OverwatchModel")] GameModel model)
: base(main, model, kernel) : base(main, model, kernel)
{ {
DisplayName = "Overwatch"; DisplayName = "Overwatch";
FindOverwatch();
}
public void FindOverwatch()
{
var gameSettings = (OverwatchSettings) GameSettings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "Overwatch.exe") &&
File.Exists(gameSettings.GameDirectory + "RzChromaSDK64.dll"))
return;
var key = Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Overwatch");
if (key == null)
return;
var path = key.GetValue("DisplayIcon").ToString();
if (!File.Exists(path))
return;
gameSettings.GameDirectory = path.Substring(0, path.Length - 14);
gameSettings.Save();
PlaceDll();
} }
public void BrowseDirectory() public void BrowseDirectory()
@ -48,28 +22,9 @@ namespace Artemis.Modules.Games.Overwatch
return; return;
((OverwatchSettings) GameSettings).GameDirectory = dialog.SelectedPath; ((OverwatchSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save(); GameSettings.Save();
((OverwatchModel) GameModel).PlaceDll();
PlaceDll(); NotifyOfPropertyChange(() => GameSettings);
}
public void PlaceDll()
{
var path = ((OverwatchSettings) GameSettings).GameDirectory;
if (!File.Exists(path + @"\Overwatch.exe"))
{
DialogService.ShowErrorMessageBox("Please select a valid Overwatch directory\n\n" +
@"By default Overwatch is in C:\Program Files (x86)\Overwatch");
((OverwatchSettings) GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
return;
}
DllManager.PlaceRazerDll(path);
} }
} }
} }

View File

@ -17,8 +17,8 @@ namespace Artemis.Modules.Games.RocketLeague
private Memory _memory; private Memory _memory;
private GamePointersCollection _pointer; private GamePointersCollection _pointer;
public RocketLeagueModel(MainManager mainManager) public RocketLeagueModel(DeviceManager deviceManager)
: base(mainManager, SettingsProvider.Load<RocketLeagueSettings>(), new RocketLeagueDataModel()) : base(deviceManager, SettingsProvider.Load<RocketLeagueSettings>(), new RocketLeagueDataModel())
{ {
Name = "RocketLeague"; Name = "RocketLeague";
ProcessName = "RocketLeague"; ProcessName = "RocketLeague";

View File

@ -1,9 +1,10 @@
using Artemis.DAL; using Artemis.DAL;
using Ninject;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Settings; using Artemis.Settings;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.RocketLeague namespace Artemis.Modules.Games.RocketLeague
{ {
@ -11,7 +12,7 @@ namespace Artemis.Modules.Games.RocketLeague
{ {
private string _versionText; private string _versionText;
public RocketLeagueViewModel(MainManager main, IKernel kernel, RocketLeagueModel model) public RocketLeagueViewModel(MainManager main, IKernel kernel, [Named("RocketLeagueModel")] GameModel model)
: base(main, model, kernel) : base(main, model, kernel)
{ {
DisplayName = "Rocket League"; DisplayName = "Rocket League";

View File

@ -12,12 +12,14 @@ namespace Artemis.Modules.Games.TheDivision
{ {
public class TheDivisionModel : GameModel public class TheDivisionModel : GameModel
{ {
private readonly PipeServer _pipeServer;
private StickyValue<bool> _stickyAmmo; private StickyValue<bool> _stickyAmmo;
private StickyValue<bool> _stickyHp; private StickyValue<bool> _stickyHp;
public TheDivisionModel(MainManager mainManager) public TheDivisionModel(DeviceManager deviceManager, PipeServer pipeServer)
: base(mainManager, SettingsProvider.Load<TheDivisionSettings>(), new TheDivisionDataModel()) : base(deviceManager, SettingsProvider.Load<TheDivisionSettings>(), new TheDivisionDataModel())
{ {
_pipeServer = pipeServer;
Name = "TheDivision"; Name = "TheDivision";
ProcessName = "TheDivision"; ProcessName = "TheDivision";
Scale = 4; Scale = 4;
@ -41,7 +43,7 @@ namespace Artemis.Modules.Games.TheDivision
_stickyAmmo.Dispose(); _stickyAmmo.Dispose();
_stickyHp.Dispose(); _stickyHp.Dispose();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage; _pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose(); base.Dispose();
} }
@ -54,7 +56,7 @@ namespace Artemis.Modules.Games.TheDivision
DllManager.PlaceLogitechDll(); DllManager.PlaceLogitechDll();
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage; _pipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true; Initialized = true;
} }

View File

@ -1,12 +1,13 @@
using Ninject; using Ninject;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.TheDivision namespace Artemis.Modules.Games.TheDivision
{ {
public sealed class TheDivisionViewModel : GameViewModel public sealed class TheDivisionViewModel : GameViewModel
{ {
public TheDivisionViewModel(MainManager main, IKernel kernel, TheDivisionModel model) public TheDivisionViewModel(MainManager main, IKernel kernel, [Named("TheDivisionModel")] GameModel model)
: base(main, model, kernel) : base(main, model, kernel)
{ {
DisplayName = "The Division"; DisplayName = "The Division";

View File

@ -1,22 +1,35 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Timers; using System.Timers;
using Artemis.DAL; using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models; using Artemis.Models;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.Utilities.DataReaders;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Artemis.Modules.Games.UnrealTournament namespace Artemis.Modules.Games.UnrealTournament
{ {
public class UnrealTournamentModel : GameModel public class UnrealTournamentModel : GameModel
{ {
private readonly PipeServer _pipeServer;
private readonly MetroDialogService _dialogService;
private Timer _killTimer; private Timer _killTimer;
private int _lastScore; private int _lastScore;
public UnrealTournamentModel(MainManager mainManager) public UnrealTournamentModel(DeviceManager deviceManager, PipeServer pipeServer, MetroDialogService dialogService)
: base(mainManager, SettingsProvider.Load<UnrealTournamentSettings>(), new UnrealTournamentDataModel()) : base(deviceManager, SettingsProvider.Load<UnrealTournamentSettings>(), new UnrealTournamentDataModel())
{ {
_pipeServer = pipeServer;
_dialogService = dialogService;
Name = "UnrealTournament"; Name = "UnrealTournament";
ProcessName = "UE4-Win64-Shipping"; ProcessName = "UE4-Win64-Shipping";
Scale = 4; Scale = 4;
@ -25,6 +38,77 @@ namespace Artemis.Modules.Games.UnrealTournament
_killTimer = new Timer(3500); _killTimer = new Timer(3500);
_killTimer.Elapsed += KillTimerOnElapsed; _killTimer.Elapsed += KillTimerOnElapsed;
FindGame();
}
public void FindGame()
{
var gameSettings = (UnrealTournamentSettings)Settings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) &&
File.Exists(gameSettings.GameDirectory + "UE4-Win64-Shipping.exe"))
return;
// Attempt to read the file
if (!File.Exists(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"))
return;
var json =
JsonConvert.DeserializeObject<JObject>(
File.ReadAllText(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"));
var utEntry =
json["InstallationList"].Children()
.FirstOrDefault(c => c["AppName"].Value<string>() == "UnrealTournamentDev");
if (utEntry == null)
return;
var utDir = utEntry["InstallLocation"].Value<string>();
// Use backslash in path for consistency
utDir = utDir.Replace('/', '\\');
if (!File.Exists(utDir + @"\UE4-Win64-Shipping.exe"))
return;
gameSettings.GameDirectory = utDir;
gameSettings.Save();
PlaceFiles();
}
public void PlaceFiles()
{
var gameSettings = (UnrealTournamentSettings)Settings;
var path = gameSettings.GameDirectory;
if (!File.Exists(path + @"\UE4-Win64-Shipping.exe"))
{
_dialogService.ShowErrorMessageBox("Please select a valid Unreal Tournament directory\n\n" +
@"By default Unreal Tournament is in C:\Program Files\Epic Games\UnrealTournament");
gameSettings.GameDirectory = string.Empty;
gameSettings.Save();
Logger?.Warn("Failed to install Unreal Tournament plugin in '{0}' (path not found)", path);
return;
}
// Load the ZIP from resources
using (var stream = new MemoryStream(Resources.ut_plugin))
{
var archive = new ZipArchive(stream);
try
{
Directory.CreateDirectory(path + @"\UnrealTournament\Plugins\Artemis");
archive.ExtractToDirectory(path + @"\UnrealTournament\Plugins\Artemis", true);
}
catch (Exception e)
{
Logger?.Error(e, "Failed to install Unreal Tournament plugin in '{0}'", path);
return;
}
}
Logger?.Info("Installed Unreal Tournament plugin in '{0}'", path);
} }
public int Scale { get; set; } public int Scale { get; set; }
@ -34,13 +118,13 @@ namespace Artemis.Modules.Games.UnrealTournament
Initialized = false; Initialized = false;
_killTimer.Stop(); _killTimer.Stop();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage; _pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose(); base.Dispose();
} }
public override void Enable() public override void Enable()
{ {
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage; _pipeServer.PipeMessage += PipeServerOnPipeMessage;
_killTimer.Start(); _killTimer.Start();
Initialized = true; Initialized = true;

View File

@ -1,65 +1,24 @@
using System; using System.Windows.Forms;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Artemis.DAL; using Artemis.DAL;
using Ninject;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Newtonsoft.Json; using Ninject;
using Newtonsoft.Json.Linq;
namespace Artemis.Modules.Games.UnrealTournament namespace Artemis.Modules.Games.UnrealTournament
{ {
public sealed class UnrealTournamentViewModel : GameViewModel public sealed class UnrealTournamentViewModel : GameViewModel
{ {
public UnrealTournamentViewModel(MainManager main, IKernel kernel, UnrealTournamentModel model) public UnrealTournamentViewModel(MainManager main, IKernel kernel,
: base(main, model, kernel) [Named("UnrealTournamentModel")] GameModel model) : base(main, model, kernel)
{ {
DisplayName = "Unreal Tournament"; DisplayName = "Unreal Tournament";
MainManager.EffectManager.EffectModels.Add(GameModel);
FindGame();
InstallGif(); InstallGif();
} }
public UnrealTournamentModel UnrealTournamentModel { get; set; } public UnrealTournamentModel UnrealTournamentModel { get; set; }
public void FindGame()
{
var gameSettings = (UnrealTournamentSettings) GameSettings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) &&
File.Exists(gameSettings.GameDirectory + "UE4-Win64-Shipping.exe"))
return;
// Attempt to read the file
if (!File.Exists(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"))
return;
var json =
JsonConvert.DeserializeObject<JObject>(
File.ReadAllText(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"));
var utEntry =
json["InstallationList"].Children()
.FirstOrDefault(c => c["AppName"].Value<string>() == "UnrealTournamentDev");
if (utEntry == null)
return;
var utDir = utEntry["InstallLocation"].Value<string>();
// Use backslash in path for consistency
utDir = utDir.Replace('/', '\\');
if (!File.Exists(utDir + @"\UE4-Win64-Shipping.exe"))
return;
gameSettings.GameDirectory = utDir;
gameSettings.Save();
PlaceFiles();
}
public void BrowseDirectory() public void BrowseDirectory()
{ {
@ -72,48 +31,12 @@ namespace Artemis.Modules.Games.UnrealTournament
return; return;
((UnrealTournamentSettings) GameSettings).GameDirectory = dialog.SelectedPath; ((UnrealTournamentSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save(); GameSettings.Save();
((UnrealTournamentModel) GameModel).PlaceFiles();
PlaceFiles(); NotifyOfPropertyChange(() => GameSettings);
}
public void PlaceFiles()
{
var path = ((UnrealTournamentSettings) GameSettings).GameDirectory;
if (!File.Exists(path + @"\UE4-Win64-Shipping.exe"))
{
DialogService.ShowErrorMessageBox("Please select a valid Unreal Tournament directory\n\n" +
@"By default Unreal Tournament is in C:\Program Files\Epic Games\UnrealTournament");
((UnrealTournamentSettings) GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
MainManager.Logger.Warn("Failed to install Unreal Tournament plugin in '{0}' (path not found)", path);
return;
}
// Load the ZIP from resources
using (var stream = new MemoryStream(Resources.ut_plugin))
{
var archive = new ZipArchive(stream);
try
{
Directory.CreateDirectory(path + @"\UnrealTournament\Plugins\Artemis");
archive.ExtractToDirectory(path + @"\UnrealTournament\Plugins\Artemis", true);
}
catch (Exception e)
{
MainManager.Logger.Error(e, "Failed to install Unreal Tournament plugin in '{0}'", path);
return;
}
}
MainManager.Logger.Info("Installed Unreal Tournament plugin in '{0}'", path);
} }
// Installing GIF on editor open to make sure the proper profiles are loaded
private void InstallGif() private void InstallGif()
{ {
var gif = Resources.redeemer; var gif = Resources.redeemer;

View File

@ -17,8 +17,8 @@ namespace Artemis.Modules.Games.Witcher3
private readonly Stopwatch _updateSw; private readonly Stopwatch _updateSw;
private string _witcherSettings; private string _witcherSettings;
public Witcher3Model(MainManager mainManager) public Witcher3Model(DeviceManager deviceManager)
: base(mainManager, SettingsProvider.Load<Witcher3Settings>(), new Witcher3DataModel()) : base(deviceManager, SettingsProvider.Load<Witcher3Settings>(), new Witcher3DataModel())
{ {
Name = "Witcher3"; Name = "Witcher3";
ProcessName = "witcher3"; ProcessName = "witcher3";

View File

@ -3,19 +3,19 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Windows.Forms; using System.Windows.Forms;
using Ninject;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.Witcher3 namespace Artemis.Modules.Games.Witcher3
{ {
public sealed class Witcher3ViewModel : GameViewModel public sealed class Witcher3ViewModel : GameViewModel
{ {
public Witcher3ViewModel(MainManager main, IKernel kernel, Witcher3Model model) public Witcher3ViewModel(MainManager main, IKernel kernel, [Named("Witcher3Model")] GameModel model)
: base(main, model, kernel) : base(main, model, kernel)
{ {
DisplayName = "The Witcher 3"; DisplayName = "The Witcher 3";

View File

@ -8,7 +8,6 @@ using Artemis.Modules.Games.WoW.Data;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Settings; using Artemis.Settings;
using Artemis.Utilities.Memory; using Artemis.Utilities.Memory;
using Newtonsoft.Json;
using Process.NET; using Process.NET;
using Process.NET.Memory; using Process.NET.Memory;
@ -19,8 +18,8 @@ namespace Artemis.Modules.Games.WoW
private readonly GamePointersCollection _pointer; private readonly GamePointersCollection _pointer;
private ProcessSharp _process; private ProcessSharp _process;
public WoWModel(MainManager mainManager) public WoWModel(DeviceManager deviceManager)
: base(mainManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel()) : base(deviceManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
{ {
Name = "WoW"; Name = "WoW";
ProcessName = "Wow-64"; ProcessName = "Wow-64";
@ -29,11 +28,11 @@ namespace Artemis.Modules.Games.WoW
// Currently WoW is locked behind a hidden trigger (obviously not that hidden if you're reading this) // Currently WoW is locked behind a hidden trigger (obviously not that hidden if you're reading this)
// It is using memory reading and lets first try to contact Blizzard // It is using memory reading and lets first try to contact Blizzard
var settings = SettingsProvider.Load<GeneralSettings>(); var settings = SettingsProvider.Load<GeneralSettings>();
Enabled = settings.GamestatePort == 62575 && Settings.Enabled; Enabled = (settings.GamestatePort == 62575) && Settings.Enabled;
Initialized = false; Initialized = false;
_pointer = SettingsProvider.Load<OffsetSettings>().WorldOfWarcraft; _pointer = SettingsProvider.Load<OffsetSettings>().WorldOfWarcraft;
//_pointer = new GamePointersCollection //_pointer = new GamePointersCollection
//{ //{
// Game = "WorldOfWarcraft", // Game = "WorldOfWarcraft",
@ -103,7 +102,7 @@ namespace Artemis.Modules.Games.WoW
_pointer.GameAddresses.First(a => a.Description == "TargetGuid").BasePointer, true); _pointer.GameAddresses.First(a => a.Description == "TargetGuid").BasePointer, true);
dataModel.Player = player; dataModel.Player = player;
if (dataModel.Player != null && dataModel.Player.Guid != Guid.Empty) if ((dataModel.Player != null) && (dataModel.Player.Guid != Guid.Empty))
{ {
dataModel.Player.UpdateDetails(nameCache); dataModel.Player.UpdateDetails(nameCache);
var target = player.GetTarget(objectManager); var target = player.GetTarget(objectManager);

View File

@ -1,12 +1,13 @@
using Ninject; using Artemis.Managers;
using Artemis.Managers; using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.WoW namespace Artemis.Modules.Games.WoW
{ {
public sealed class WoWViewModel : GameViewModel public sealed class WoWViewModel : GameViewModel
{ {
public WoWViewModel(MainManager main, IKernel kernel, WoWModel model) public WoWViewModel(MainManager main, IKernel kernel, [Named("WoWModel")] GameModel model)
: base(main, model, kernel) : base(main, model, kernel)
{ {
DisplayName = "WoW"; DisplayName = "WoW";

View File

@ -13,12 +13,11 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
{ {
public class VolumeDisplayModel : OverlayModel public class VolumeDisplayModel : OverlayModel
{ {
public VolumeDisplayModel(MainManager mainManager) public VolumeDisplayModel(DeviceManager deviceManager): base(deviceManager, SettingsProvider.Load<VolumeDisplaySettings>())
: base(mainManager, SettingsProvider.Load<VolumeDisplaySettings>())
{ {
Name = "VolumeDisplay"; Name = "VolumeDisplay";
Settings = (VolumeDisplaySettings) base.Settings; Settings = (VolumeDisplaySettings) base.Settings;
VolumeDisplay = new VolumeBar(MainManager.DeviceManager, Settings); VolumeDisplay = new VolumeBar(DeviceManager, Settings);
} }
public new VolumeDisplaySettings Settings { get; set; } public new VolumeDisplaySettings Settings { get; set; }
@ -79,7 +78,7 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
public override void RenderOverlay(RenderFrame frame, bool keyboardOnly) public override void RenderOverlay(RenderFrame frame, bool keyboardOnly)
{ {
if ((MainManager.DeviceManager.ActiveKeyboard == null) || (VolumeDisplay == null) || (VolumeDisplay.Ttl < 1)) if ((DeviceManager.ActiveKeyboard == null) || (VolumeDisplay == null) || (VolumeDisplay.Ttl < 1))
return; return;
using (var g = Graphics.FromImage(frame.KeyboardBitmap)) using (var g = Graphics.FromImage(frame.KeyboardBitmap))

View File

@ -1,6 +1,8 @@
using System.Windows.Media; using System.Windows.Media;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Overlays.VolumeDisplay namespace Artemis.Modules.Overlays.VolumeDisplay
{ {
@ -10,13 +12,14 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
private SolidColorBrush _mainColor; private SolidColorBrush _mainColor;
private SolidColorBrush _secondaryColor; private SolidColorBrush _secondaryColor;
public VolumeDisplayViewModel(MainManager mainManager, VolumeDisplayModel model) : base(mainManager, model) public VolumeDisplayViewModel(MainManager mainManager, [Named("VolumeDisplayModel")] OverlayModel model)
: base(mainManager, model)
{ {
_model = model; _model = (VolumeDisplayModel) model;
DisplayName = "Volume Display"; DisplayName = "Volume Display";
MainColor = new SolidColorBrush(model.Settings.MainColor); MainColor = new SolidColorBrush(_model.Settings.MainColor);
SecondaryColor = new SolidColorBrush(model.Settings.SecondaryColor); SecondaryColor = new SolidColorBrush(_model.Settings.SecondaryColor);
} }
public Brush MainColor public Brush MainColor

View File

@ -47,8 +47,12 @@ namespace Artemis.Profiles.Layers.Types.Generic
layer.AppliedProperties.Width*4, layer.AppliedProperties.Width*4,
layer.AppliedProperties.Height*4); layer.AppliedProperties.Height*4);
// Can't meddle with the original brush because it's frozen.
var brush = layer.AppliedProperties.Brush.Clone();
brush.Opacity = layer.AppliedProperties.Opacity;
c.PushClip(new RectangleGeometry(rect)); c.PushClip(new RectangleGeometry(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect); c.DrawRectangle(brush, null, rect);
c.Pop(); c.Pop();
} }

View File

@ -45,8 +45,12 @@ namespace Artemis.Profiles.Layers.Types.Headset
layer.AppliedProperties.Width*4, layer.AppliedProperties.Width*4,
layer.AppliedProperties.Height*4); layer.AppliedProperties.Height*4);
// Can't meddle with the original brush because it's frozen.
var brush = layer.AppliedProperties.Brush.Clone();
brush.Opacity = layer.AppliedProperties.Opacity;
c.PushClip(new RectangleGeometry(rect)); c.PushClip(new RectangleGeometry(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect); c.DrawRectangle(brush, null, rect);
c.Pop(); c.Pop();
} }

View File

@ -57,9 +57,12 @@ namespace Artemis.Profiles.Layers.Types.Keyboard
var clip = new Rect(layer.AppliedProperties.X*4, layer.AppliedProperties.Y*4, var clip = new Rect(layer.AppliedProperties.X*4, layer.AppliedProperties.Y*4,
layer.AppliedProperties.Width*4, layer.AppliedProperties.Height*4); layer.AppliedProperties.Width*4, layer.AppliedProperties.Height*4);
// Can't meddle with the original brush because it's frozen.
var brush = layer.AppliedProperties.Brush.Clone();
brush.Opacity = layer.AppliedProperties.Opacity;
c.PushClip(new RectangleGeometry(clip)); c.PushClip(new RectangleGeometry(clip));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect); c.DrawRectangle(brush, null, rect);
c.Pop(); c.Pop();
} }

View File

@ -47,8 +47,12 @@ namespace Artemis.Profiles.Layers.Types.Mouse
layer.AppliedProperties.Width*4, layer.AppliedProperties.Width*4,
layer.AppliedProperties.Height*4); layer.AppliedProperties.Height*4);
// Can't meddle with the original brush because it's frozen.
var brush = layer.AppliedProperties.Brush.Clone();
brush.Opacity = layer.AppliedProperties.Opacity;
c.PushClip(new RectangleGeometry(rect)); c.PushClip(new RectangleGeometry(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect); c.DrawRectangle(brush, null, rect);
c.Pop(); c.Pop();
} }

View File

@ -45,8 +45,12 @@ namespace Artemis.Profiles.Layers.Types.Mousemat
layer.AppliedProperties.Width*4, layer.AppliedProperties.Width*4,
layer.AppliedProperties.Height*4); layer.AppliedProperties.Height*4);
// Can't meddle with the original brush because it's frozen.
var brush = layer.AppliedProperties.Brush.Clone();
brush.Opacity = layer.AppliedProperties.Opacity;
c.PushClip(new RectangleGeometry(rect)); c.PushClip(new RectangleGeometry(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect); c.DrawRectangle(brush, null, rect);
c.Pop(); c.Pop();
} }

View File

@ -82,7 +82,7 @@ namespace Artemis.Profiles.Lua
private static void LuaPrint(string s) private static void LuaPrint(string s)
{ {
Logger.Debug("[{0}-LUA]: {1}", ProfileModel.Name, s); Logger.Debug("[{0}-LUA]: {1}", ProfileModel?.Name, s);
} }
#endregion #endregion

View File

@ -11,7 +11,6 @@ using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Lua; using Artemis.Profiles.Lua;
using Artemis.Utilities; using Artemis.Utilities;
using Artemis.Utilities.ParentChild; using Artemis.Utilities.ParentChild;
using Newtonsoft.Json;
using Color = System.Windows.Media.Color; using Color = System.Windows.Media.Color;
using Point = System.Windows.Point; using Point = System.Windows.Point;
using Size = System.Windows.Size; using Size = System.Windows.Size;
@ -25,12 +24,6 @@ namespace Artemis.Profiles
Layers = new ChildItemCollection<ProfileModel, LayerModel>(this); Layers = new ChildItemCollection<ProfileModel, LayerModel>(this);
} }
/// <summary>
/// Indicates whether the profile is actively being rendered
/// </summary>
[JsonIgnore]
public bool IsActive { get; set; }
public ChildItemCollection<ProfileModel, LayerModel> Layers { get; } public ChildItemCollection<ProfileModel, LayerModel> Layers { get; }
public string Name { get; set; } public string Name { get; set; }
public bool IsDefault { get; set; } public bool IsDefault { get; set; }
@ -171,6 +164,34 @@ namespace Artemis.Profiles
} }
} }
public void Activate(KeyboardProvider keyboard)
{
if (!Equals(LuaWrapper.ProfileModel, this))
LuaWrapper.SetupLua(this, keyboard);
}
public void Deactivate()
{
if (Equals(LuaWrapper.ProfileModel, this))
LuaWrapper.Clear();
}
public LayerModel AddLayer(LayerModel afterLayer)
{
// Create a new layer
var layer = LayerModel.CreateLayer();
if (afterLayer != null)
afterLayer.InsertAfter(layer);
else
{
Layers.Add(layer);
FixOrder();
}
return layer;
}
#region Compare #region Compare
protected bool Equals(ProfileModel other) protected bool Equals(ProfileModel other)
@ -200,37 +221,5 @@ namespace Artemis.Profiles
} }
#endregion #endregion
public void Activate(KeyboardProvider keyboard)
{
if (!Equals(LuaWrapper.ProfileModel, this))
{
LuaWrapper.SetupLua(this, keyboard);
}
}
public void Deactivate()
{
if (Equals(LuaWrapper.ProfileModel, this))
{
LuaWrapper.Clear();
}
}
public LayerModel AddLayer(LayerModel afterLayer)
{
// Create a new layer
var layer = LayerModel.CreateLayer();
if (afterLayer!= null)
afterLayer.InsertAfter(layer);
else
{
Layers.Add(layer);
FixOrder();
}
return layer;
}
} }
} }

View File

@ -13,20 +13,22 @@ namespace Artemis.Services
_kernel = kernel; _kernel = kernel;
} }
public void ShowWindow<T>(params IParameter[] param) where T : class public T ShowWindow<T>(params IParameter[] param) where T : class
{ {
var windowManager = new WindowManager(); var windowManager = new WindowManager();
var viewModel = _kernel.Get<T>(param); var viewModel = _kernel.Get<T>(param);
windowManager.ShowWindow(viewModel); windowManager.ShowWindow(viewModel);
return viewModel;
} }
public void ShowDialog<T>(params IParameter[] param) where T : class public T ShowDialog<T>(params IParameter[] param) where T : class
{ {
var windowManager = new WindowManager(); var windowManager = new WindowManager();
var viewModel = _kernel.Get<T>(param); var viewModel = _kernel.Get<T>(param);
windowManager.ShowDialog(viewModel); windowManager.ShowDialog(viewModel);
return viewModel;
} }
} }
} }

View File

@ -1,10 +1,15 @@
using Artemis.DAL; using System.ComponentModel;
using Artemis.DAL;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Artemis.Settings namespace Artemis.Settings
{ {
public class EffectSettings : IArtemisSettings public class EffectSettings : IArtemisSettings
{ {
[DefaultValue("Default")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public string LastProfile { get; set; }
public void Save() public void Save()
{ {
SettingsProvider.Save(this); SettingsProvider.Save(this);

View File

@ -8,9 +8,5 @@ namespace Artemis.Settings
[DefaultValue(true)] [DefaultValue(true)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public bool Enabled { get; set; } public bool Enabled { get; set; }
[DefaultValue("Default")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public string LastProfile { get; set; }
} }
} }

View File

@ -50,6 +50,9 @@ namespace Artemis.Utilities
public static System.Windows.Media.Color FromHex(this System.Windows.Media.Color c, string hex) public static System.Windows.Media.Color FromHex(this System.Windows.Media.Color c, string hex)
{ {
if (hex == null)
return new System.Windows.Media.Color();
var convertFromString = ColorConverter.ConvertFromString(hex); var convertFromString = ColorConverter.ConvertFromString(hex);
if (convertFromString != null) if (convertFromString != null)
return (System.Windows.Media.Color) convertFromString; return (System.Windows.Media.Color) convertFromString;

View File

@ -62,6 +62,7 @@ namespace Artemis.Utilities.GameState
private void ListenerRun() private void ListenerRun()
{ {
// TODO: Check for UI issue
while (Running) while (Running)
{ {
_listener.BeginGetContext(HandleRequest, _listener); _listener.BeginGetContext(HandleRequest, _listener);

View File

@ -29,7 +29,6 @@ namespace Artemis.ViewModels.Abstract
new ConstructorArgument("lastProfile", GameSettings.LastProfile) new ConstructorArgument("lastProfile", GameSettings.LastProfile)
}; };
ProfileEditor = kernel.Get<ProfileEditorViewModel>(args); ProfileEditor = kernel.Get<ProfileEditorViewModel>(args);
GameModel.Profile = ProfileEditor.SelectedProfile;
ProfileEditor.PropertyChanged += ProfileUpdater; ProfileEditor.PropertyChanged += ProfileUpdater;
} }
@ -98,9 +97,11 @@ namespace Artemis.ViewModels.Abstract
GameModel.Profile = ProfileEditor.SelectedProfile; GameModel.Profile = ProfileEditor.SelectedProfile;
ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile; ProfilePreviewModel.Profile = ProfileEditor.SelectedProfile;
// Only update the last selected profile if it the editor was active and the new profile isn't null
if ((e.PropertyName != "SelectedProfile") || !ProfileEditor.ProfileViewModel.Activated || if ((e.PropertyName != "SelectedProfile") || !ProfileEditor.ProfileViewModel.Activated ||
(ProfileEditor.ProfileViewModel.SelectedProfile == null)) (ProfileEditor.ProfileViewModel.SelectedProfile == null))
return; return;
GameSettings.LastProfile = ProfileEditor.ProfileViewModel.SelectedProfile.Name; GameSettings.LastProfile = ProfileEditor.ProfileViewModel.SelectedProfile.Name;
GameSettings.Save(); GameSettings.Save();
} }

View File

@ -5,20 +5,20 @@ namespace Artemis.ViewModels
{ {
public sealed class EffectsViewModel : BaseViewModel public sealed class EffectsViewModel : BaseViewModel
{ {
private readonly EffectViewModel[] _effectViewModels; private IOrderedEnumerable<EffectViewModel> _vms;
public EffectsViewModel(EffectViewModel[] effectViewModels) public EffectsViewModel(EffectViewModel[] effectViewModels)
{ {
DisplayName = "Effects"; DisplayName = "Effects";
_effectViewModels = effectViewModels;
_vms = effectViewModels.OrderBy(o => o.DisplayName);
} }
protected override void OnActivate() protected override void OnActivate()
{ {
base.OnActivate(); base.OnActivate();
Items.Clear();
foreach (var effectViewModel in _effectViewModels.OrderBy(e => e.DisplayName)) Items.AddRange(_vms);
ActivateItem(effectViewModel);
} }
} }
} }

View File

@ -1,39 +1,30 @@
using System.Linq; using System.Linq;
using Artemis.DAL;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Modules.Effects.ProfilePreview; using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Modules.Games.WoW;
using Artemis.Settings;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
namespace Artemis.ViewModels namespace Artemis.ViewModels
{ {
public sealed class GamesViewModel : BaseViewModel public sealed class GamesViewModel : BaseViewModel
{ {
private readonly GameViewModel[] _gameViewModels; private IOrderedEnumerable<GameViewModel> _vms;
public GamesViewModel(GameViewModel[] gameViewModels, ProfileManager profileManager, public GamesViewModel(GameViewModel[] gameViewModels, ProfileManager profileManager,
ProfilePreviewModel profilePreviewModel) ProfilePreviewModel profilePreviewModel)
{ {
DisplayName = "Games"; DisplayName = "Games";
_gameViewModels = gameViewModels;
_vms = gameViewModels.OrderBy(g => g.DisplayName);
profileManager.ProfilePreviewModel = profilePreviewModel; profileManager.ProfilePreviewModel = profilePreviewModel;
profileManager.GameViewModels.AddRange(_gameViewModels); profileManager.GameViewModels.AddRange(_vms);
} }
protected override void OnActivate() protected override void OnActivate()
{ {
base.OnActivate(); base.OnActivate();
Items.Clear();
var settings = SettingsProvider.Load<GeneralSettings>(); Items.AddRange(_vms);
foreach (var gameViewModel in _gameViewModels.OrderBy(g => g.DisplayName))
{
if (settings.GamestatePort != 62575 && gameViewModel is WoWViewModel)
continue;
ActivateItem(gameViewModel);
}
} }
} }
} }

View File

@ -1,23 +1,23 @@
using Artemis.ViewModels.Abstract; using System.Linq;
using Artemis.ViewModels.Abstract;
namespace Artemis.ViewModels namespace Artemis.ViewModels
{ {
public sealed class OverlaysViewModel : BaseViewModel public sealed class OverlaysViewModel : BaseViewModel
{ {
private readonly OverlayViewModel[] _overlayViewModels; private IOrderedEnumerable<OverlayViewModel> _vms;
public OverlaysViewModel(OverlayViewModel[] overlayViewModels) public OverlaysViewModel(OverlayViewModel[] overlayViewModels)
{ {
DisplayName = "Overlays"; DisplayName = "Overlays";
_overlayViewModels = overlayViewModels; _vms = overlayViewModels.OrderBy(o => o.DisplayName);
} }
protected override void OnActivate() protected override void OnActivate()
{ {
base.OnActivate(); base.OnActivate();
Items.Clear();
foreach (var overlayViewModel in _overlayViewModels) Items.AddRange(_vms);
ActivateItem(overlayViewModel);
} }
} }
} }

View File

@ -35,8 +35,8 @@ namespace Artemis.ViewModels.Profiles
{ {
public sealed class ProfileEditorViewModel : Screen, IDropTarget public sealed class ProfileEditorViewModel : Screen, IDropTarget
{ {
private readonly DeviceManager _deviceManager;
private readonly EffectModel _gameModel; private readonly EffectModel _gameModel;
private readonly MainManager _mainManager;
private readonly Timer _saveTimer; private readonly Timer _saveTimer;
private ImageSource _keyboardPreview; private ImageSource _keyboardPreview;
private BindableCollection<LayerModel> _layers; private BindableCollection<LayerModel> _layers;
@ -44,10 +44,11 @@ namespace Artemis.ViewModels.Profiles
private bool _saving; private bool _saving;
private ProfileModel _selectedProfile; private ProfileModel _selectedProfile;
public ProfileEditorViewModel(MainManager mainManager, EffectModel gameModel, ProfileViewModel profileViewModel, public ProfileEditorViewModel(DeviceManager deviceManager, EffectModel gameModel,
MetroDialogService dialogService, WindowService windowService, string lastProfile) ProfileViewModel profileViewModel, MetroDialogService dialogService, WindowService windowService,
string lastProfile)
{ {
_mainManager = mainManager; _deviceManager = deviceManager;
_gameModel = gameModel; _gameModel = gameModel;
ProfileNames = new BindableCollection<string>(); ProfileNames = new BindableCollection<string>();
@ -59,7 +60,7 @@ namespace Artemis.ViewModels.Profiles
PropertyChanged += EditorStateHandler; PropertyChanged += EditorStateHandler;
ProfileViewModel.PropertyChanged += LayerSelectedHandler; ProfileViewModel.PropertyChanged += LayerSelectedHandler;
mainManager.DeviceManager.OnKeyboardChangedEvent += DeviceManagerOnOnKeyboardChangedEvent; _deviceManager.OnKeyboardChangedEvent += DeviceManagerOnOnKeyboardChangedEvent;
_saveTimer = new Timer(5000); _saveTimer = new Timer(5000);
_saveTimer.Elapsed += ProfileSaveHandler; _saveTimer.Elapsed += ProfileSaveHandler;
@ -77,9 +78,7 @@ namespace Artemis.ViewModels.Profiles
public ProfileViewModel ProfileViewModel { get; set; } public ProfileViewModel ProfileViewModel { get; set; }
public bool EditorEnabled public bool EditorEnabled
=> => (SelectedProfile != null) && !SelectedProfile.IsDefault && (_deviceManager.ActiveKeyboard != null);
(SelectedProfile != null) && !SelectedProfile.IsDefault &&
(_mainManager.DeviceManager.ActiveKeyboard != null);
public BindableCollection<string> ProfileNames public BindableCollection<string> ProfileNames
{ {
@ -111,11 +110,7 @@ namespace Artemis.ViewModels.Profiles
if (value == SelectedProfile?.Name) if (value == SelectedProfile?.Name)
return; return;
SelectedProfile = ProfileProvider.GetProfile( SelectedProfile = ProfileProvider.GetProfile(_deviceManager.ActiveKeyboard, _gameModel, value);
_mainManager.DeviceManager.ActiveKeyboard,
_gameModel,
value);
NotifyOfPropertyChange(() => SelectedProfileName); NotifyOfPropertyChange(() => SelectedProfileName);
} }
} }
@ -143,7 +138,7 @@ namespace Artemis.ViewModels.Profiles
} }
} }
public PreviewSettings? PreviewSettings => _mainManager.DeviceManager.ActiveKeyboard?.PreviewSettings; public PreviewSettings? PreviewSettings => _deviceManager.ActiveKeyboard?.PreviewSettings;
public bool ProfileSelected => SelectedProfile != null; public bool ProfileSelected => SelectedProfile != null;
public bool LayerSelected => (SelectedProfile != null) && (ProfileViewModel.SelectedLayer != null); public bool LayerSelected => (SelectedProfile != null) && (ProfileViewModel.SelectedLayer != null);
@ -243,28 +238,23 @@ namespace Artemis.ViewModels.Profiles
private void LoadProfiles() private void LoadProfiles()
{ {
ProfileNames.Clear(); ProfileNames.Clear();
if ((_gameModel == null) || (_mainManager.DeviceManager.ActiveKeyboard == null)) if ((_gameModel == null) || (_deviceManager.ActiveKeyboard == null))
return; return;
ProfileNames.AddRange(ProfileProvider.GetProfileNames(_mainManager.DeviceManager.ActiveKeyboard, _gameModel)); ProfileNames.AddRange(ProfileProvider.GetProfileNames(_deviceManager.ActiveKeyboard, _gameModel));
// If a profile name was provided, try to load it // If a profile name was provided, try to load it
ProfileModel lastProfileModel = null; ProfileModel lastProfileModel = null;
if (!string.IsNullOrEmpty(LastProfile)) if (!string.IsNullOrEmpty(LastProfile))
{ {
lastProfileModel = ProfileProvider.GetProfile( lastProfileModel = ProfileProvider.GetProfile(_deviceManager.ActiveKeyboard, _gameModel, LastProfile);
_mainManager.DeviceManager.ActiveKeyboard,
_gameModel,
LastProfile);
} }
if (lastProfileModel != null) if (lastProfileModel != null)
SelectedProfile = lastProfileModel; SelectedProfile = lastProfileModel;
else else
{ {
SelectedProfile = ProfileProvider.GetProfile( SelectedProfile = ProfileProvider.GetProfile(_deviceManager.ActiveKeyboard, _gameModel,
_mainManager.DeviceManager.ActiveKeyboard,
_gameModel,
ProfileNames.FirstOrDefault()); ProfileNames.FirstOrDefault());
} }
} }
@ -296,7 +286,8 @@ namespace Artemis.ViewModels.Profiles
if (layer == null) if (layer == null)
return; return;
IParameter[] args = { IParameter[] args =
{
new ConstructorArgument("dataModel", _gameModel.DataModel), new ConstructorArgument("dataModel", _gameModel.DataModel),
new ConstructorArgument("layer", layer) new ConstructorArgument("layer", layer)
}; };
@ -480,7 +471,7 @@ namespace Artemis.ViewModels.Profiles
/// </summary> /// </summary>
public async void AddProfile() public async void AddProfile()
{ {
if (_mainManager.DeviceManager.ActiveKeyboard == null) if (_deviceManager.ActiveKeyboard == null)
{ {
DialogService.ShowMessageBox("Cannot add profile.", DialogService.ShowMessageBox("Cannot add profile.",
"To add a profile, please select a keyboard in the options menu first."); "To add a profile, please select a keyboard in the options menu first.");
@ -503,9 +494,9 @@ namespace Artemis.ViewModels.Profiles
var profile = new ProfileModel var profile = new ProfileModel
{ {
Name = name, Name = name,
KeyboardSlug = _mainManager.DeviceManager.ActiveKeyboard.Slug, KeyboardSlug = _deviceManager.ActiveKeyboard.Slug,
Width = _mainManager.DeviceManager.ActiveKeyboard.Width, Width = _deviceManager.ActiveKeyboard.Width,
Height = _mainManager.DeviceManager.ActiveKeyboard.Height, Height = _deviceManager.ActiveKeyboard.Height,
GameName = _gameModel.Name GameName = _gameModel.Name
}; };
@ -601,7 +592,7 @@ namespace Artemis.ViewModels.Profiles
public async void ImportProfile() public async void ImportProfile()
{ {
if (_mainManager.DeviceManager.ActiveKeyboard == null) if (_deviceManager.ActiveKeyboard == null)
{ {
DialogService.ShowMessageBox("Cannot import profile.", DialogService.ShowMessageBox("Cannot import profile.",
"To import a profile, please select a keyboard in the options menu first."); "To import a profile, please select a keyboard in the options menu first.");
@ -629,7 +620,7 @@ namespace Artemis.ViewModels.Profiles
} }
// Verify the keyboard // Verify the keyboard
var deviceManager = _mainManager.DeviceManager; var deviceManager = _deviceManager;
if (profile.KeyboardSlug != deviceManager.ActiveKeyboard.Slug) if (profile.KeyboardSlug != deviceManager.ActiveKeyboard.Slug)
{ {
var adjustKeyboard = await DialogService.ShowQuestionMessageBox("Profile not inteded for this keyboard", var adjustKeyboard = await DialogService.ShowQuestionMessageBox("Profile not inteded for this keyboard",
@ -687,7 +678,7 @@ namespace Artemis.ViewModels.Profiles
return; return;
try try
{ {
SelectedProfile?.Activate(_mainManager.DeviceManager.ActiveKeyboard); SelectedProfile?.Activate(_deviceManager.ActiveKeyboard);
LuaWrapper.OpenEditor(); LuaWrapper.OpenEditor();
} }
catch (Exception e) catch (Exception e)

View File

@ -1,6 +1,5 @@
using System.Linq; using System;
using Artemis.Managers; using System.Linq;
using Artemis.Services;
using Artemis.ViewModels.Abstract; using Artemis.ViewModels.Abstract;
using Artemis.ViewModels.Flyouts; using Artemis.ViewModels.Flyouts;
using Caliburn.Micro; using Caliburn.Micro;
@ -10,17 +9,18 @@ namespace Artemis.ViewModels
{ {
public sealed class ShellViewModel : Conductor<IScreen>.Collection.OneActive public sealed class ShellViewModel : Conductor<IScreen>.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 // Setup UI
DisplayName = "Artemis"; DisplayName = "Artemis";
Flyouts = new BindableCollection<FlyoutBaseViewModel> Flyouts = new BindableCollection<FlyoutBaseViewModel>
{ {
kernel.Get<FlyoutSettingsViewModel>() flyoutSettings
}; };
} }
@ -29,10 +29,16 @@ namespace Artemis.ViewModels
protected override void OnActivate() protected override void OnActivate()
{ {
base.OnActivate(); base.OnActivate();
foreach (var screen in _viewModels) Items.Clear();
ActivateItem(screen);
ActiveItem = _viewModels.FirstOrDefault(); var vms = _kernel.GetAll<BaseViewModel>();
Items.AddRange(vms);
}
protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
Items.Clear();
} }
public void Settings() public void Settings()

View File

@ -14,18 +14,16 @@ namespace Artemis.ViewModels
{ {
public class SystemTrayViewModel : Screen public class SystemTrayViewModel : Screen
{ {
private readonly ShellViewModel _shellViewModel; private readonly WindowService _windowService;
private readonly IWindowManager _windowManager; private ShellViewModel _shellViewModel;
private string _activeIcon; private string _activeIcon;
private bool _checked; private bool _checked;
private bool _enabled; private bool _enabled;
private string _toggleText; private string _toggleText;
public SystemTrayViewModel(IWindowManager windowManager, MetroDialogService dialogService, public SystemTrayViewModel(WindowService windowService, MetroDialogService dialogService, MainManager mainManager)
ShellViewModel shellViewModel, MainManager mainManager)
{ {
_windowManager = windowManager; _windowService = windowService;
_shellViewModel = shellViewModel;
DialogService = dialogService; DialogService = dialogService;
MainManager = mainManager; MainManager = mainManager;
@ -43,8 +41,17 @@ namespace Artemis.ViewModels
public MainManager MainManager { get; set; } public MainManager MainManager { get; set; }
public bool CanShowWindow => !_shellViewModel.IsActive; public bool CanShowWindow
public bool CanHideWindow => _shellViewModel.IsActive && !MainManager.DeviceManager.ChangingKeyboard; {
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 CanToggleEnabled => !MainManager.DeviceManager.ChangingKeyboard;
public bool Enabled public bool Enabled
@ -111,7 +118,7 @@ namespace Artemis.ViewModels
return; return;
// manually show the next window view-model // manually show the next window view-model
_windowManager.ShowWindow(_shellViewModel); _shellViewModel = _windowService.ShowWindow<ShellViewModel>();
NotifyOfPropertyChange(() => CanShowWindow); NotifyOfPropertyChange(() => CanShowWindow);
NotifyOfPropertyChange(() => CanHideWindow); NotifyOfPropertyChange(() => CanHideWindow);

View File

@ -104,6 +104,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LOGILEDCORSAIR_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BrowseInformation>true</BrowseInformation>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -111,6 +112,9 @@
<ModuleDefinitionFile>LogiLed2Artemis.def</ModuleDefinitionFile> <ModuleDefinitionFile>LogiLed2Artemis.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<Bscmake>
<PreserveSbr>true</PreserveSbr>
</Bscmake>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile> <ClCompile>
@ -151,12 +155,10 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Logger.h" />
<ClInclude Include="LogiLedDefs.h" /> <ClInclude Include="LogiLedDefs.h" />
<ClInclude Include="main.h" /> <ClInclude Include="main.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Logger.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -21,17 +21,11 @@
<ClInclude Include="LogiLedDefs.h"> <ClInclude Include="LogiLedDefs.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Logger.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="LogiLed2Artemis.def"> <None Include="LogiLed2Artemis.def">

View File

@ -30,69 +30,50 @@
#include "LogiLedDefs.h" #include "LogiLedDefs.h"
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
#include "Logger.h"
#include <complex> #include <complex>
#include <filesystem> #include <filesystem>
#include <fstream>
using namespace std;
static bool g_hasInitialised = false; static bool g_hasInitialised = false;
static bool mustLog = false;
const char* game = ""; const char* game = "";
void cleanup()
{
CLogger::EndLogging();
}
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID) 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); ofstream myfile;
myfile.open("log.txt", ios::out | ios::app);
CLogger::InitLogging("Log.txt"); myfile << "Main called, DLL loaded into " << szPath << "\n";
CLogger::SetLogLevel(LogLevel::None); myfile.close();
// 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);
} }
break;
case DLL_PROCESS_DETACH:
{
cleanup();
CLogger::OutputLog_s("Detached from process.", LogLevel::Debug);
}
break;
} }
return true; return true;
} }
bool LogiLedInit() bool LogiLedInit()
{ {
CLogger::OutputLog_s("Logitech LED init called.", LogLevel::Debug);
g_hasInitialised = true; g_hasInitialised = true;
return true; return true;
} }
bool LogiLedGetSdkVersion(int* majorNum, int* minorNum, int* buildNum) bool LogiLedGetSdkVersion(int* majorNum, int* minorNum, int* buildNum)
{ {
CLogger::OutputLog("LogiLedGetSdkVersion called.", LogLevel::Debug);
// Mimic the SDK version // Mimic the SDK version
*majorNum = 8; *majorNum = 8;
*minorNum = 81; *minorNum = 81;
@ -103,15 +84,12 @@ bool LogiLedGetSdkVersion(int* majorNum, int* minorNum, int* buildNum)
bool LogiLedSetTargetDevice(int targetDevice) 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 // Logitech SDK says this function returns false if LogiLedInit hasn't been called
return g_hasInitialised; return g_hasInitialised;
} }
bool LogiLedSaveCurrentLighting() bool LogiLedSaveCurrentLighting()
{ {
CLogger::OutputLog("LogiLedSaveCurrentLighting called (%i)", LogLevel::Debug);
return true; return true;
} }
@ -125,21 +103,39 @@ void Transmit(const char* msg)
hPipe1 = CreateFile(lpszPipename1, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); hPipe1 = CreateFile(lpszPipename1, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (hPipe1 == NULL || hPipe1 == INVALID_HANDLE_VALUE) 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; return;
} }
DWORD cbWritten; DWORD cbWritten;
WriteFile(hPipe1, msg, strlen(msg), &cbWritten, NULL); 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); if (mustLog)
{
std::ostringstream os; ofstream myfile;
os << "0 0 " << redPercentage << " " << greenPercentage << " " << bluePercentage; 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()); Transmit(os.str().c_str());
return true; return true;
@ -147,108 +143,209 @@ bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercenta
bool LogiLedRestoreLighting() 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; return true;
} }
bool LogiLedFlashLighting(int redPercentage, int greenPercentage, int bluePercentage, int milliSecondsDuration, int milliSecondsInterval) 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; return true;
} }
bool LogiLedPulseLighting(int redPercentage, int greenPercentage, int bluePercentage, int milliSecondsDuration, int milliSecondsInterval) 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; return true;
} }
bool LogiLedStopEffects() 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; return true;
} }
bool LogiLedSetLightingFromBitmap(unsigned char bitmap[]) 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; return true;
} }
bool LogiLedSetLightingForKeyWithScanCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage) 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; return true;
} }
bool LogiLedSetLightingForKeyWithHidCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage) 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; return true;
} }
bool LogiLedSetLightingForKeyWithQuartzCode(int keyCode, int redPercentage, int greenPercentage, int bluePercentage) 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; return true;
} }
bool LogiLedSetLightingForKeyWithKeyName(LogiLed::KeyName keyName, int redPercentage, int greenPercentage, int bluePercentage) 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. // Only transmit interesting keys. This can most likely be done prettier, but I'm no C++ dev.
if (game == "division" && if (game == "division" && (keyName == LogiLed::F1 || keyName == LogiLed::F2 || keyName == LogiLed::F3 || keyName == LogiLed::F4 || keyName == LogiLed::R || keyName == LogiLed::G || keyName == LogiLed::V))
(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; os << "1 " << keyName << " " << redPercentage << " " << greenPercentage << " " << bluePercentage;
std::string s = os.str(); string s = os.str();
Transmit(os.str().c_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; return true;
} }
bool LogiLedSaveLightingForKey(LogiLed::KeyName keyName) 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; return true;
} }
bool LogiLedRestoreLightingForKey(LogiLed::KeyName keyName) 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; return true;
} }
bool LogiLedFlashSingleKey(LogiLed::KeyName keyName, int redPercentage, int greenPercentage, int bluePercentage, int msDuration, int msInterval) 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; return true;
} }
bool LogiLedPulseSingleKey(LogiLed::KeyName keyName, int startRedPercentage, int startGreenPercentage, int startBluePercentage, int finishRedPercentage, int finishGreenPercentage, int finishBluePercentage, int msDuration, bool isInfinite) 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; return true;
} }
bool LogiLedStopEffectsOnKey(LogiLed::KeyName keyName) 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; return true;
} }
void LogiLedShutdown() 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; g_hasInitialised = false;
} }