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

View File

@ -367,6 +367,13 @@
<DependentUpon>EurotruckSimulator2View.xaml</DependentUpon>
</Compile>
<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\UnrealTournamentModel.cs" />
<Compile Include="Modules\Games\UnrealTournament\UnrealTournamentSettings.cs" />
@ -763,6 +770,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Modules\Games\GtaV\GtaVView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Modules\Games\Overwatch\OverwatchView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -1,9 +1,10 @@
using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Services;
using Artemis.Utilities.DataReaders;
using Artemis.Utilities.GameState;
using Artemis.ViewModels;
using Artemis.ViewModels.Abstract;
using Artemis.ViewModels.Profiles;
using Caliburn.Micro;
using Ninject.Modules;
namespace Artemis.InjectionModules
@ -13,15 +14,15 @@ namespace Artemis.InjectionModules
public override void Load()
{
// ViewModels
Bind<IScreen>().To<ShellViewModel>().InSingletonScope();
Bind<ShellViewModel>().ToSelf();
Bind<ProfileViewModel>().ToSelf();
Bind<ProfileEditorViewModel>().ToSelf();
Bind<DebugViewModel>().ToSelf().InSingletonScope();
Bind<BaseViewModel>().To<WelcomeViewModel>().InSingletonScope();
Bind<BaseViewModel>().To<EffectsViewModel>().InSingletonScope();
Bind<BaseViewModel>().To<GamesViewModel>().InSingletonScope();
Bind<BaseViewModel>().To<OverlaysViewModel>().InSingletonScope();
Bind<BaseViewModel>().To<WelcomeViewModel>();
Bind<BaseViewModel>().To<EffectsViewModel>();
Bind<BaseViewModel>().To<GamesViewModel>();
Bind<BaseViewModel>().To<OverlaysViewModel>();
// Models
Bind<ProfilePreviewModel>().ToSelf().InSingletonScope();
@ -29,6 +30,10 @@ namespace Artemis.InjectionModules
// Services
Bind<MetroDialogService>().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()
.InheritedFrom<EffectModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
.Configure((b, c) => b.InSingletonScope().Named(c.Name));
});
// View models
Kernel.Bind(x =>
{
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<EffectViewModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
});
// Games
Kernel.Bind(x =>
{
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<GameModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
.BindBase();
});
Kernel.Bind(x =>
@ -43,27 +33,14 @@ namespace Artemis.InjectionModules
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<GameViewModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
.BindBase();
});
// Overlays
Kernel.Bind(x =>
{
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<OverlayModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
});
Kernel.Bind(x =>
{
x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<OverlayViewModel>()
.BindBase()
.Configure(b => b.InSingletonScope());
.BindBase();
});
}
}

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@ namespace Artemis.Models
{
public abstract class GameModel : EffectModel
{
protected GameModel(MainManager mainManager, GameSettings settings, IDataModel dataModel): base(mainManager, settings, dataModel)
protected GameModel(DeviceManager deviceManager, GameSettings settings, IDataModel dataModel): base(deviceManager, settings, dataModel)
{
// Override settings to the GameSettings type
Settings = settings;

View File

@ -8,7 +8,7 @@ namespace Artemis.Models
private bool _enabled;
public string ProcessName;
protected OverlayModel(MainManager mainManager, OverlaySettings settings) : base(mainManager, settings, null)
protected OverlayModel(DeviceManager deviceManager, OverlaySettings settings) : base(deviceManager, settings, null)
{
Settings = settings;
Enabled = settings.Enabled;

View File

@ -1,12 +1,14 @@
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Effects.ProfilePreview;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Effects.AudioVisualizer
{
public sealed class AudioVisualizerViewModel : EffectViewModel
{
public AudioVisualizerViewModel(MainManager main, ProfilePreviewModel model) : base(main, model)
public AudioVisualizerViewModel(MainManager main, [Named("ProfilePreviewModel")] EffectModel model) : base(main, model)
{
DisplayName = "Audio Visualization / Key waves";
}

View File

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

View File

@ -1,6 +1,8 @@
using System.Windows.Media;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Effects.Bubbles
{
@ -9,11 +11,11 @@ namespace Artemis.Modules.Effects.Bubbles
private readonly BubblesModel _model;
private SolidColorBrush _bubbleColor;
public BubblesViewModel(MainManager main, BubblesModel model) : base(main, model)
public BubblesViewModel(MainManager main, [Named("BubblesModel")] EffectModel model) : base(main, model)
{
_model = model;
_model = (BubblesModel) model;
DisplayName = "Bubbles";
BubbleColor = new SolidColorBrush(model.Settings.BubbleColor);
BubbleColor = new SolidColorBrush(_model.Settings.BubbleColor);
}
/// <summary>

View File

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

View File

@ -9,25 +9,22 @@ using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
using Newtonsoft.Json;
using Ninject.Extensions.Logging;
using SpotifyAPI.Local;
namespace Artemis.Modules.Effects.WindowsProfile
{
public class WindowsProfileModel : EffectModel
{
private readonly ILogger _logger;
private List<PerformanceCounter> _cores;
private int _cpuFrames;
private DateTime _lastMusicUpdate;
private PerformanceCounter _overallCpu;
private SpotifyLocalAPI _spotify;
private bool _spotifySetupBusy;
private DateTime _lastMusicUpdate;
public WindowsProfileModel(ILogger logger, MainManager mainManager)
: base(mainManager, SettingsProvider.Load<WindowsProfileSettings>(), new WindowsProfileDataModel())
public WindowsProfileModel(DeviceManager deviceManager)
: base(deviceManager, SettingsProvider.Load<WindowsProfileSettings>(), new WindowsProfileDataModel())
{
_logger = logger;
_lastMusicUpdate = DateTime.Now;
Name = "WindowsProfile";
@ -85,7 +82,7 @@ namespace Artemis.Modules.Effects.WindowsProfile
}
catch (InvalidOperationException)
{
_logger.Warn("Failed to setup CPU information, try running \"lodctr /R\" as administrator.");
Logger?.Warn("Failed to setup CPU information, try running \"lodctr /R\" as administrator.");
}
}
@ -220,10 +217,8 @@ namespace Artemis.Modules.Effects.WindowsProfile
}
if (dataModel.Spotify.SongLength > 0)
{
dataModel.Spotify.SongPercentCompleted =
(int) (status.PlayingPosition/dataModel.Spotify.SongLength*100.0);
}
}
private void UpdateGooglePlayMusic(WindowsProfileDataModel dataModel)

View File

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

View File

@ -1,48 +1,57 @@
using System;
using System.Collections.Generic;
using System.IO;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.GameState;
using Newtonsoft.Json;
using Ninject.Extensions.Logging;
namespace Artemis.Modules.Games.CounterStrike
{
public class CounterStrikeModel : GameModel
{
private readonly MetroDialogService _dialogService;
private readonly GameStateWebServer _gameStateWebServer;
private DateTime _lastHeadshot;
private int _lastHeadshots;
private DateTime _lastKill;
private int _lastKills;
public CounterStrikeModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<CounterStrikeSettings>(), new CounterStrikeDataModel())
public CounterStrikeModel(DeviceManager deviceManager, GameStateWebServer gameStateWebServer,
MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<CounterStrikeSettings>(), new CounterStrikeDataModel())
{
_gameStateWebServer = gameStateWebServer;
_dialogService = dialogService;
Name = "CounterStrike";
ProcessName = "csgo";
Scale = 4;
Enabled = Settings.Enabled;
Initialized = false;
FindGameDir();
PlaceConfigFile();
}
public ILogger Logger { get; set; }
public int Scale { get; set; }
public override void Dispose()
{
Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData;
_gameStateWebServer.GameDataReceived -= HandleGameData;
base.Dispose();
}
public override void Enable()
{
Initialized = false;
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
_gameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true;
}
@ -90,6 +99,42 @@ namespace Artemis.Modules.Games.CounterStrike
DataModel = dm;
}
public void FindGameDir()
{
var gameSettings = (CounterStrikeSettings) Settings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") &&
File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg"))
return;
var dir = GeneralHelpers.FindSteamGame(@"\Counter-Strike Global Offensive\csgo.exe");
gameSettings.GameDirectory = dir ?? string.Empty;
gameSettings.Save();
}
public void PlaceConfigFile()
{
var gameSettings = (CounterStrikeSettings) Settings;
if (gameSettings.GameDirectory == string.Empty)
return;
var path = gameSettings.GameDirectory;
if (Directory.Exists(path + "/csgo/cfg"))
{
var cfgFile = Resources.csgoGamestateConfiguration.Replace("{{port}}",
_gameStateWebServer.Port.ToString());
File.WriteAllText(path + "/csgo/cfg/gamestate_integration_artemis.cfg", cfgFile);
return;
}
_dialogService.ShowErrorMessageBox("Please select a valid CS:GO directory\n\n" +
@"By default CS:GO is in \SteamApps\common\Counter-Strike Global Offensive");
gameSettings.GameDirectory = string.Empty;
gameSettings.Save();
}
public void HandleGameData(object sender, GameDataReceivedEventArgs e)
{
var jsonString = e.Json.ToString();
@ -112,6 +157,7 @@ namespace Artemis.Modules.Games.CounterStrike
}
}
public override List<LayerModel> GetRenderLayers(bool keyboardOnly)
{
return Profile.GetRenderLayers(DataModel, keyboardOnly);

View File

@ -1,72 +1,22 @@
using System.IO;
using System.Windows.Forms;
using Ninject;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.CounterStrike
{
public sealed class CounterStrikeViewModel : GameViewModel
{
public CounterStrikeViewModel(MainManager main, IKernel kernel, CounterStrikeModel model)
public CounterStrikeViewModel(MainManager main, IKernel kernel, [Named("CounterStrikeModel")] GameModel model)
: base(main, model, kernel)
{
DisplayName = "CS:GO";
FindGameDir();
PlaceConfigFile();
}
public void FindGameDir()
{
var gameSettings = (CounterStrikeSettings) GameSettings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") &&
File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg"))
return;
var dir = GeneralHelpers.FindSteamGame(@"\Counter-Strike Global Offensive\csgo.exe");
gameSettings.GameDirectory = dir ?? string.Empty;
gameSettings.Save();
}
public void BrowseDirectory()
{
var dialog = new FolderBrowserDialog {SelectedPath = ((CounterStrikeSettings) GameSettings).GameDirectory};
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
((CounterStrikeSettings) GameSettings).GameDirectory = Path.GetDirectoryName(dialog.SelectedPath);
((CounterStrikeModel) GameModel).PlaceConfigFile();
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceConfigFile();
}
public void PlaceConfigFile()
{
if (((CounterStrikeSettings) GameSettings).GameDirectory == string.Empty)
return;
var path = ((CounterStrikeSettings) GameSettings).GameDirectory;
if (Directory.Exists(path + "/csgo/cfg"))
{
var cfgFile = Resources.csgoGamestateConfiguration.Replace("{{port}}",
MainManager.GameStateWebServer.Port.ToString());
File.WriteAllText(path + "/csgo/cfg/gamestate_integration_artemis.cfg", cfgFile);
return;
}
DialogService.ShowErrorMessageBox("Please select a valid CS:GO directory\n\n" +
@"By default CS:GO is in \SteamApps\common\Counter-Strike Global Offensive");
((CounterStrikeSettings) GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
}
}
}

View File

@ -1,8 +1,12 @@
using System.Collections.Generic;
using System.IO;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.GameState;
using Newtonsoft.Json;
@ -10,14 +14,24 @@ namespace Artemis.Modules.Games.Dota2
{
public class Dota2Model : GameModel
{
public Dota2Model(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<Dota2Settings>(), new Dota2DataModel())
private readonly MetroDialogService _dialogService;
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";
ProcessName = "dota2";
Enabled = Settings.Enabled;
Initialized = false;
Scale = 4;
FindGameDir();
PlaceConfigFile();
}
public int Scale { get; set; }
@ -25,13 +39,13 @@ namespace Artemis.Modules.Games.Dota2
public override void Dispose()
{
Initialized = false;
MainManager.GameStateWebServer.GameDataReceived -= HandleGameData;
_gameStateWebServer.GameDataReceived -= HandleGameData;
base.Dispose();
}
public override void Enable()
{
MainManager.GameStateWebServer.GameDataReceived += HandleGameData;
_gameStateWebServer.GameDataReceived += HandleGameData;
Initialized = true;
}
@ -40,6 +54,55 @@ namespace Artemis.Modules.Games.Dota2
UpdateDay();
}
public void FindGameDir()
{
var gameSettings = (Dota2Settings) Settings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") &&
File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg"))
return;
var dir = GeneralHelpers.FindSteamGame(@"\dota 2 beta\game\bin\win32\dota2.exe");
// Remove subdirectories where they stuck the executable
dir = dir?.Substring(0, dir.Length - 15);
gameSettings.GameDirectory = dir ?? string.Empty;
gameSettings.Save();
}
public void PlaceConfigFile()
{
var gameSettings = (Dota2Settings) Settings;
if (gameSettings.GameDirectory == string.Empty)
return;
if (Directory.Exists(gameSettings.GameDirectory + "/game/dota/cfg"))
{
var cfgFile = Resources.dotaGamestateConfiguration.Replace("{{port}}",
_gameStateWebServer.Port.ToString());
try
{
File.WriteAllText(
gameSettings.GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg", cfgFile);
}
catch (DirectoryNotFoundException)
{
Directory.CreateDirectory(gameSettings.GameDirectory + "/game/dota/cfg/gamestate_integration/");
File.WriteAllText(
gameSettings.GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
return;
}
_dialogService.ShowErrorMessageBox("Please select a valid Dota 2 directory\n\n" +
@"By default Dota 2 is in \SteamApps\common\dota 2 beta");
gameSettings.GameDirectory = string.Empty;
gameSettings.Save();
}
private void UpdateDay()
{
var dataModel = DataModel as Dota2DataModel;

View File

@ -1,88 +1,22 @@
using System.IO;
using System.Windows.Forms;
using Ninject;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.Dota2
{
public sealed class Dota2ViewModel : GameViewModel
{
public Dota2ViewModel(MainManager main, IKernel kernel, Dota2Model model)
public Dota2ViewModel(MainManager main, IKernel kernel, [Named("Dota2Model")] GameModel model)
: base(main, model, kernel)
{
DisplayName = "Dota 2";
FindGameDir();
PlaceConfigFile();
}
public void FindGameDir()
{
var gameSettings = (Dota2Settings) GameSettings;
// If already propertly set up, don't do anything
if ((gameSettings.GameDirectory != null) && File.Exists(gameSettings.GameDirectory + "csgo.exe") &&
File.Exists(gameSettings.GameDirectory + "/csgo/cfg/gamestate_integration_artemis.cfg"))
return;
var dir = GeneralHelpers.FindSteamGame(@"\dota 2 beta\game\bin\win32\dota2.exe");
// Remove subdirectories where they stuck the executable
dir = dir?.Substring(0, dir.Length - 15);
gameSettings.GameDirectory = dir ?? string.Empty;
gameSettings.Save();
}
public void BrowseDirectory()
{
var dialog = new FolderBrowserDialog {SelectedPath = ((Dota2Settings) GameSettings).GameDirectory};
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
((Dota2Settings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceConfigFile();
}
public void PlaceConfigFile()
{
if (((Dota2Settings) GameSettings).GameDirectory == string.Empty)
return;
if (Directory.Exists(((Dota2Settings) GameSettings).GameDirectory + "/game/dota/cfg"))
{
var cfgFile = Resources.dotaGamestateConfiguration.Replace("{{port}}",
MainManager.GameStateWebServer.Port.ToString());
try
{
File.WriteAllText(
((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
catch (DirectoryNotFoundException)
{
Directory.CreateDirectory(((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/");
File.WriteAllText(
((Dota2Settings) GameSettings).GameDirectory +
"/game/dota/cfg/gamestate_integration/gamestate_integration_artemis.cfg",
cfgFile);
}
return;
}
DialogService.ShowErrorMessageBox("Please select a valid Dota 2 directory\n\n" +
@"By default Dota 2 is in \SteamApps\common\dota 2 beta");
((Dota2Settings) GameSettings).GameDirectory = string.Empty;
((Dota2Model) GameModel).PlaceConfigFile();
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
}
}
}

View File

@ -1,27 +1,37 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Modules.Games.EurotruckSimulator2.Data;
using Artemis.Profiles.Layers.Models;
using Artemis.Properties;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Ninject.Extensions.Logging;
namespace Artemis.Modules.Games.EurotruckSimulator2
{
public class EurotruckSimulator2Model : GameModel
{
public EurotruckSimulator2Model(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<EurotruckSimulator2Settings>(), new EurotruckSimulator2DataModel()
)
private readonly MetroDialogService _dialogService;
public EurotruckSimulator2Model(DeviceManager deviceManager, MetroDialogService dialogService)
: base(
deviceManager, SettingsProvider.Load<EurotruckSimulator2Settings>(), new EurotruckSimulator2DataModel())
{
_dialogService = dialogService;
Name = "EurotruckSimulator2";
ProcessName = "eurotrucks2";
Scale = 4;
Enabled = Settings.Enabled;
Initialized = false;
FindGameDir();
}
public ILogger Logger { get; set; }
public int Scale { get; set; }
public override void Dispose()
@ -47,6 +57,66 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
dataModel.Truck = telemetryData.Truck;
}
public void FindGameDir()
{
var gameSettings = (EurotruckSimulator2Settings) Settings;
// Demo is also supported but resides in a different directory, the full game can also be 64-bits
var dir = GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x64\eurotrucks2.exe") ??
GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x86\eurotrucks2.exe") ??
GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2 Demo\bin\win_x86\eurotrucks2.exe");
if (string.IsNullOrEmpty(dir))
return;
gameSettings.GameDirectory = dir;
gameSettings.Save();
if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll"))
PlacePlugin();
}
public void PlacePlugin()
{
var gameSettings = (EurotruckSimulator2Settings) Settings;
if (gameSettings.GameDirectory == string.Empty)
return;
var path = gameSettings.GameDirectory;
// Ensure the selected directory exists
if (!Directory.Exists(path))
{
_dialogService.ShowErrorMessageBox($"Directory '{path}' not found.");
return;
}
// Ensure it's the ETS2 directory by looking for the executable
if (!File.Exists(path + "/eurotrucks2.exe"))
{
_dialogService.ShowErrorMessageBox("Please select a valid Eurotruck Simulator 2 directory\n\n" +
@"By default ETS2 is in \SteamApps\common\Euro Truck Simulator 2\bin\win_x64");
return;
}
// Create the plugins folder if it's not already there
Directory.CreateDirectory(path + "/plugins");
// Place either the 64-bits or 32-bits DLL
try
{
if (path.Contains("win_x64"))
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x64);
else
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x86);
Logger?.Debug("Installed ETS2 plugin in {0}", path);
}
catch (Exception e)
{
Logger?.Error(e, "Failed to install ETS2 plugin in {0}", path);
throw;
}
}
public override List<LayerModel> GetRenderLayers(bool 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 Ninject;
using Artemis.Managers;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.EurotruckSimulator2
{
public sealed class EurotruckSimulator2ViewModel : GameViewModel
{
public EurotruckSimulator2ViewModel(MainManager main, IKernel kernel,
EurotruckSimulator2Model model) : base(main, model, kernel)
[Named("EurotruckSimulator2Model")] GameModel model) : base(main, model, kernel)
{
DisplayName = "ETS 2";
FindGameDir();
}
public void FindGameDir()
{
var gameSettings = (EurotruckSimulator2Settings) GameSettings;
// Demo is also supported but resides in a different directory, the full game can also be 64-bits
var dir = GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x64\eurotrucks2.exe") ??
GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2\bin\win_x86\eurotrucks2.exe") ??
GeneralHelpers.FindSteamGame(@"\Euro Truck Simulator 2 Demo\bin\win_x86\eurotrucks2.exe");
if (string.IsNullOrEmpty(dir))
return;
gameSettings.GameDirectory = dir;
gameSettings.Save();
if (!File.Exists(dir + "/plugins/ets2-telemetry-server.dll"))
PlacePlugin();
}
public void BrowseDirectory()
@ -51,49 +29,7 @@ namespace Artemis.Modules.Games.EurotruckSimulator2
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlacePlugin();
}
public void PlacePlugin()
{
if (((EurotruckSimulator2Settings) GameSettings).GameDirectory == string.Empty)
return;
var path = ((EurotruckSimulator2Settings) GameSettings).GameDirectory;
// Ensure the selected directory exists
if (!Directory.Exists(path))
{
DialogService.ShowErrorMessageBox($"Directory '{path}' not found.");
return;
}
// Ensure it's the ETS2 directory by looking for the executable
if (!File.Exists(path + "/eurotrucks2.exe"))
{
DialogService.ShowErrorMessageBox("Please select a valid Eurotruck Simulator 2 directory\n\n" +
@"By default ETS2 is in \SteamApps\common\Euro Truck Simulator 2\bin\win_x64");
return;
}
// Create the plugins folder if it's not already there
Directory.CreateDirectory(path + "/plugins");
// Place either the 64-bits or 32-bits DLL
try
{
if (path.Contains("win_x64"))
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x64);
else
File.WriteAllBytes(path + "/plugins/ets2-telemetry-server.dll", Resources.ets2_telemetry_server_x86);
MainManager.Logger.Debug("Installed ETS2 plugin in {0}", path);
}
catch (Exception e)
{
MainManager.Logger.Error(e, "Failed to install ETS2 plugin in {0}", path);
throw;
}
((EurotruckSimulator2Model) GameModel).PlacePlugin();
}
}
}

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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Media;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Models;
using Artemis.Settings;
using Artemis.Services;
using Artemis.Utilities;
using Artemis.Utilities.DataReaders;
using Microsoft.Win32;
namespace Artemis.Modules.Games.Overwatch
{
public class OverwatchModel : GameModel
{
private readonly PipeServer _pipeServer;
private readonly MetroDialogService _dialogService;
private DateTime _characterChange;
private string _lastMessage;
// Using sticky values on these since they can cause flickering
@ -23,9 +27,11 @@ namespace Artemis.Modules.Games.Overwatch
private DateTime _ultimateReady;
private DateTime _ultimateUsed;
public OverwatchModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<OverwatchSettings>(), new OverwatchDataModel())
public OverwatchModel(DeviceManager deviceManager, PipeServer pipeServer, MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<OverwatchSettings>(), new OverwatchDataModel())
{
_pipeServer = pipeServer;
_dialogService = dialogService;
Name = "Overwatch";
ProcessName = "Overwatch";
Scale = 4;
@ -33,11 +39,7 @@ namespace Artemis.Modules.Games.Overwatch
Initialized = false;
LoadOverwatchCharacters();
}
public OverwatchModel(MainManager mainManager, GameSettings settings, IDataModel dataModel)
: base(mainManager, settings, dataModel)
{
FindOverwatch();
}
public List<CharacterColor> OverwatchCharacters { get; set; }
@ -77,7 +79,7 @@ namespace Artemis.Modules.Games.Overwatch
_stickyStatus = new StickyValue<OverwatchStatus>(300);
_stickyUltimateReady = new StickyValue<bool>(350);
_stickyUltimateUsed = new StickyValue<bool>(350);
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
_pipeServer.PipeMessage += PipeServerOnPipeMessage;
Initialized = true;
}
@ -90,7 +92,7 @@ namespace Artemis.Modules.Games.Overwatch
_stickyUltimateReady.Dispose();
_stickyUltimateUsed.Dispose();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage;
_pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose();
}
@ -177,7 +179,7 @@ namespace Artemis.Modules.Games.Overwatch
}
catch (FormatException e)
{
MainManager.Logger.Trace(e, "Failed to parse to color array");
Logger?.Trace(e, "Failed to parse to color array");
return null;
}
}
@ -271,6 +273,46 @@ namespace Artemis.Modules.Games.Overwatch
{
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

View File

@ -1,43 +1,17 @@
using System.IO;
using System.Windows.Forms;
using Ninject;
using System.Windows.Forms;
using Artemis.Managers;
using Artemis.Utilities.DataReaders;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Microsoft.Win32;
using Ninject;
namespace Artemis.Modules.Games.Overwatch
{
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)
{
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()
@ -48,28 +22,9 @@ namespace Artemis.Modules.Games.Overwatch
return;
((OverwatchSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceDll();
}
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);
((OverwatchModel) GameModel).PlaceDll();
NotifyOfPropertyChange(() => GameSettings);
}
}
}

View File

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

View File

@ -1,9 +1,10 @@
using Artemis.DAL;
using Ninject;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.RocketLeague
{
@ -11,7 +12,7 @@ namespace Artemis.Modules.Games.RocketLeague
{
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)
{
DisplayName = "Rocket League";

View File

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

View File

@ -1,12 +1,13 @@
using Ninject;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
namespace Artemis.Modules.Games.TheDivision
{
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)
{
DisplayName = "The Division";

View File

@ -1,22 +1,35 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Timers;
using Artemis.DAL;
using Artemis.Managers;
using Artemis.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.Linq;
namespace Artemis.Modules.Games.UnrealTournament
{
public class UnrealTournamentModel : GameModel
{
private readonly PipeServer _pipeServer;
private readonly MetroDialogService _dialogService;
private Timer _killTimer;
private int _lastScore;
public UnrealTournamentModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<UnrealTournamentSettings>(), new UnrealTournamentDataModel())
public UnrealTournamentModel(DeviceManager deviceManager, PipeServer pipeServer, MetroDialogService dialogService)
: base(deviceManager, SettingsProvider.Load<UnrealTournamentSettings>(), new UnrealTournamentDataModel())
{
_pipeServer = pipeServer;
_dialogService = dialogService;
Name = "UnrealTournament";
ProcessName = "UE4-Win64-Shipping";
Scale = 4;
@ -25,6 +38,77 @@ namespace Artemis.Modules.Games.UnrealTournament
_killTimer = new Timer(3500);
_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; }
@ -34,13 +118,13 @@ namespace Artemis.Modules.Games.UnrealTournament
Initialized = false;
_killTimer.Stop();
MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage;
_pipeServer.PipeMessage -= PipeServerOnPipeMessage;
base.Dispose();
}
public override void Enable()
{
MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
_pipeServer.PipeMessage += PipeServerOnPipeMessage;
_killTimer.Start();
Initialized = true;

View File

@ -1,65 +1,24 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms;
using Artemis.DAL;
using Ninject;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Ninject;
namespace Artemis.Modules.Games.UnrealTournament
{
public sealed class UnrealTournamentViewModel : GameViewModel
{
public UnrealTournamentViewModel(MainManager main, IKernel kernel, UnrealTournamentModel model)
: base(main, model, kernel)
public UnrealTournamentViewModel(MainManager main, IKernel kernel,
[Named("UnrealTournamentModel")] GameModel model) : base(main, model, kernel)
{
DisplayName = "Unreal Tournament";
MainManager.EffectManager.EffectModels.Add(GameModel);
FindGame();
InstallGif();
}
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()
{
@ -72,48 +31,12 @@ namespace Artemis.Modules.Games.UnrealTournament
return;
((UnrealTournamentSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceFiles();
}
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);
((UnrealTournamentModel) GameModel).PlaceFiles();
NotifyOfPropertyChange(() => GameSettings);
}
// Installing GIF on editor open to make sure the proper profiles are loaded
private void InstallGif()
{
var gif = Resources.redeemer;

View File

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

View File

@ -3,19 +3,19 @@ using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Ninject;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Properties;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Games.Witcher3
{
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)
{
DisplayName = "The Witcher 3";

View File

@ -8,7 +8,6 @@ using Artemis.Modules.Games.WoW.Data;
using Artemis.Profiles.Layers.Models;
using Artemis.Settings;
using Artemis.Utilities.Memory;
using Newtonsoft.Json;
using Process.NET;
using Process.NET.Memory;
@ -19,8 +18,8 @@ namespace Artemis.Modules.Games.WoW
private readonly GamePointersCollection _pointer;
private ProcessSharp _process;
public WoWModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
public WoWModel(DeviceManager deviceManager)
: base(deviceManager, SettingsProvider.Load<WoWSettings>(), new WoWDataModel())
{
Name = "WoW";
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)
// It is using memory reading and lets first try to contact Blizzard
var settings = SettingsProvider.Load<GeneralSettings>();
Enabled = settings.GamestatePort == 62575 && Settings.Enabled;
Enabled = (settings.GamestatePort == 62575) && Settings.Enabled;
Initialized = false;
_pointer = SettingsProvider.Load<OffsetSettings>().WorldOfWarcraft;
_pointer = SettingsProvider.Load<OffsetSettings>().WorldOfWarcraft;
//_pointer = new GamePointersCollection
//{
// Game = "WorldOfWarcraft",
@ -103,7 +102,7 @@ namespace Artemis.Modules.Games.WoW
_pointer.GameAddresses.First(a => a.Description == "TargetGuid").BasePointer, true);
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);
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 Ninject;
namespace Artemis.Modules.Games.WoW
{
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)
{
DisplayName = "WoW";

View File

@ -13,12 +13,11 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
{
public class VolumeDisplayModel : OverlayModel
{
public VolumeDisplayModel(MainManager mainManager)
: base(mainManager, SettingsProvider.Load<VolumeDisplaySettings>())
public VolumeDisplayModel(DeviceManager deviceManager): base(deviceManager, SettingsProvider.Load<VolumeDisplaySettings>())
{
Name = "VolumeDisplay";
Settings = (VolumeDisplaySettings) base.Settings;
VolumeDisplay = new VolumeBar(MainManager.DeviceManager, Settings);
VolumeDisplay = new VolumeBar(DeviceManager, Settings);
}
public new VolumeDisplaySettings Settings { get; set; }
@ -79,7 +78,7 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
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;
using (var g = Graphics.FromImage(frame.KeyboardBitmap))

View File

@ -1,6 +1,8 @@
using System.Windows.Media;
using Artemis.Managers;
using Artemis.Models;
using Artemis.ViewModels.Abstract;
using Ninject;
namespace Artemis.Modules.Overlays.VolumeDisplay
{
@ -10,13 +12,14 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
private SolidColorBrush _mainColor;
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";
MainColor = new SolidColorBrush(model.Settings.MainColor);
SecondaryColor = new SolidColorBrush(model.Settings.SecondaryColor);
MainColor = new SolidColorBrush(_model.Settings.MainColor);
SecondaryColor = new SolidColorBrush(_model.Settings.SecondaryColor);
}
public Brush MainColor

View File

@ -47,8 +47,12 @@ namespace Artemis.Profiles.Layers.Types.Generic
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(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect);
c.DrawRectangle(brush, null, rect);
c.Pop();
}

View File

@ -45,8 +45,12 @@ namespace Artemis.Profiles.Layers.Types.Headset
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(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect);
c.DrawRectangle(brush, null, rect);
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,
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.DrawRectangle(layer.AppliedProperties.Brush, null, rect);
c.DrawRectangle(brush, null, rect);
c.Pop();
}

View File

@ -47,8 +47,12 @@ namespace Artemis.Profiles.Layers.Types.Mouse
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(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect);
c.DrawRectangle(brush, null, rect);
c.Pop();
}

View File

@ -45,8 +45,12 @@ namespace Artemis.Profiles.Layers.Types.Mousemat
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(rect));
c.DrawRectangle(layer.AppliedProperties.Brush, null, rect);
c.DrawRectangle(brush, null, rect);
c.Pop();
}

View File

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

View File

@ -11,7 +11,6 @@ using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Lua;
using Artemis.Utilities;
using Artemis.Utilities.ParentChild;
using Newtonsoft.Json;
using Color = System.Windows.Media.Color;
using Point = System.Windows.Point;
using Size = System.Windows.Size;
@ -25,12 +24,6 @@ namespace Artemis.Profiles
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 string Name { 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
protected bool Equals(ProfileModel other)
@ -200,37 +221,5 @@ namespace Artemis.Profiles
}
#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;
}
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 viewModel = _kernel.Get<T>(param);
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 viewModel = _kernel.Get<T>(param);
windowManager.ShowDialog(viewModel);
return viewModel;
}
}
}

View File

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

View File

@ -8,9 +8,5 @@ namespace Artemis.Settings
[DefaultValue(true)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
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)
{
if (hex == null)
return new System.Windows.Media.Color();
var convertFromString = ColorConverter.ConvertFromString(hex);
if (convertFromString != null)
return (System.Windows.Media.Color) convertFromString;

View File

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

View File

@ -29,7 +29,6 @@ namespace Artemis.ViewModels.Abstract
new ConstructorArgument("lastProfile", GameSettings.LastProfile)
};
ProfileEditor = kernel.Get<ProfileEditorViewModel>(args);
GameModel.Profile = ProfileEditor.SelectedProfile;
ProfileEditor.PropertyChanged += ProfileUpdater;
}
@ -98,9 +97,11 @@ namespace Artemis.ViewModels.Abstract
GameModel.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 ||
(ProfileEditor.ProfileViewModel.SelectedProfile == null))
return;
GameSettings.LastProfile = ProfileEditor.ProfileViewModel.SelectedProfile.Name;
GameSettings.Save();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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