From dac752aab71f083634ec4c698c3606908f8e9e25 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 16 Feb 2020 01:47:51 +0100 Subject: [PATCH] Refactor LightingStateManager ProcessManager: Watch the runing Processes and call if found a match ProfileManager: Handle the switching between Profiles (Application) LightingStateManager: Rendering the Light Events Adding a change profile animation --- Project-Aurora/Plugin-Example/PluginMain.cs | 2 +- Project-Aurora/Project-Aurora/App.xaml.cs | 4 +- .../Project-Aurora/ConfigUI.xaml.cs | 14 +- .../Controls/ColorZones.xaml.cs | 3 +- .../Controls/EffectSettingsWindow.xaml.cs | 4 +- .../Project-Aurora/Profiles/Application.cs | 27 +- .../Profiles/Desktop/Event_Desktop.cs | 6 +- .../Project-Aurora/Profiles/LightEvent.cs | 6 - .../Profiles/LightingStateManager.cs | 790 ++---------------- .../Project-Aurora/Profiles/ProcessManager.cs | 143 ++++ .../Project-Aurora/Profiles/ProfileManager.cs | 555 ++++++++++++ .../Project-Aurora/Project-Aurora.csproj | 2 + .../Project-Aurora/Settings/Configuration.cs | 5 + .../Settings/Control_Settings.xaml | 5 + .../Settings/Control_Settings.xaml.cs | 12 + .../Settings/KeyboardLayoutManager.cs | 4 +- .../Logic/Boolean/Boolean_ProcessRunning.cs | 4 +- 17 files changed, 825 insertions(+), 761 deletions(-) create mode 100644 Project-Aurora/Project-Aurora/Profiles/ProcessManager.cs create mode 100644 Project-Aurora/Project-Aurora/Profiles/ProfileManager.cs diff --git a/Project-Aurora/Plugin-Example/PluginMain.cs b/Project-Aurora/Plugin-Example/PluginMain.cs index 7039e94b2..cea4d8959 100644 --- a/Project-Aurora/Plugin-Example/PluginMain.cs +++ b/Project-Aurora/Plugin-Example/PluginMain.cs @@ -37,7 +37,7 @@ public void ProcessManager(object manager) { if (manager is LightingStateManager) { - ((LightingStateManager)manager).RegisterLayerHandler(new LayerHandlerEntry("ExampleLayer", "Example Layer", typeof(ExampleLayerHandler))); + ((ProfileManager)manager).RegisterLayerHandler(new LayerHandlerEntry("ExampleLayer", "Example Layer", typeof(ExampleLayerHandler))); } } } diff --git a/Project-Aurora/Project-Aurora/App.xaml.cs b/Project-Aurora/Project-Aurora/App.xaml.cs index 0c00df3ce..7713a83b0 100755 --- a/Project-Aurora/Project-Aurora/App.xaml.cs +++ b/Project-Aurora/Project-Aurora/App.xaml.cs @@ -112,7 +112,7 @@ public static void LogLine(this NLog.Logger logger, string text, Logging_Level l //public static GameEventHandler geh; public static PluginManager PluginManager; - public static LightingStateManager LightingStateManager; + public static ProfileManager LightingStateManager; public static NetworkListener net_listener; public static Configuration Configuration; public static DeviceManager dev_manager; @@ -353,7 +353,7 @@ protected override void OnStartup(StartupEventArgs e) } Global.logger.Info("Loading Applications"); - (Global.LightingStateManager = new LightingStateManager()).Initialize(); + (Global.LightingStateManager = new ProfileManager()).Initialize(); if (Global.Configuration.GetPointerUpdates) { diff --git a/Project-Aurora/Project-Aurora/ConfigUI.xaml.cs b/Project-Aurora/Project-Aurora/ConfigUI.xaml.cs index 863abb12a..1ef8670d6 100755 --- a/Project-Aurora/Project-Aurora/ConfigUI.xaml.cs +++ b/Project-Aurora/Project-Aurora/ConfigUI.xaml.cs @@ -44,7 +44,8 @@ partial class ConfigUI : Window, INotifyPropertyChanged private bool settingsloaded = false; private bool shownHiddenMessage = false; - private string saved_preview_key = ""; + private string saved_preview_key = null; + public string preview_key => saved_preview_key; private Timer virtual_keyboard_timer; private Stopwatch recording_stopwatch = new Stopwatch(); @@ -64,7 +65,9 @@ public Profiles.Application FocusedApplication set { SetValue(FocusedApplicationProperty, value); - Global.LightingStateManager.PreviewProfileKey = value != null ? value.Config.ID : string.Empty; + saved_preview_key = value != null ? value.Config.ID : null; + + Global.LightingStateManager.FocusedApplicationChanged(saved_preview_key); } } @@ -332,8 +335,6 @@ private void minimizeApp() shownHiddenMessage = true; } - Global.LightingStateManager.PreviewProfileKey = string.Empty; - //Hide Window System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, (System.Windows.Threading.DispatcherOperationCallback)delegate (object o) { @@ -345,13 +346,12 @@ private void minimizeApp() private void Window_Activated(object sender, EventArgs e) { - Global.LightingStateManager.PreviewProfileKey = saved_preview_key; + Global.LightingStateManager.FocusedApplicationChanged(saved_preview_key); } private void Window_Deactivated(object sender, EventArgs e) { - saved_preview_key = Global.LightingStateManager.PreviewProfileKey; - Global.LightingStateManager.PreviewProfileKey = string.Empty; + Global.LightingStateManager.FocusedApplicationChanged(null); } private Image profile_add; diff --git a/Project-Aurora/Project-Aurora/Controls/ColorZones.xaml.cs b/Project-Aurora/Project-Aurora/Controls/ColorZones.xaml.cs index 56fbc7fb1..894fca34d 100644 --- a/Project-Aurora/Project-Aurora/Controls/ColorZones.xaml.cs +++ b/Project-Aurora/Project-Aurora/Controls/ColorZones.xaml.cs @@ -168,7 +168,8 @@ private void effect_settings_button_Click(object sender, RoutedEventArgs e) if (cz_list.SelectedItem != null) { EffectSettingsWindow effect_settings = new EffectSettingsWindow(((ColorZone)cz_list.SelectedItem).effect_config); - effect_settings.preview_key = Global.LightingStateManager.PreviewProfileKey; + + effect_settings.preview_key = ((ConfigUI)System.Windows.Application.Current.MainWindow).preview_key; effect_settings.EffectConfigUpdated += Effect_settings_EffectConfigUpdated; effect_settings.ShowDialog(); diff --git a/Project-Aurora/Project-Aurora/Controls/EffectSettingsWindow.xaml.cs b/Project-Aurora/Project-Aurora/Controls/EffectSettingsWindow.xaml.cs index 3099c6b5b..cf6da3426 100644 --- a/Project-Aurora/Project-Aurora/Controls/EffectSettingsWindow.xaml.cs +++ b/Project-Aurora/Project-Aurora/Controls/EffectSettingsWindow.xaml.cs @@ -122,12 +122,12 @@ private void accept_button_Click(object sender, RoutedEventArgs e) private void Window_Activated(object sender, EventArgs e) { - Global.LightingStateManager.PreviewProfileKey = preview_key; + Global.LightingStateManager.FocusedApplicationChanged(null); } private void Window_Deactivated(object sender, EventArgs e) { - Global.LightingStateManager.PreviewProfileKey = null; + Global.LightingStateManager.FocusedApplicationChanged(preview_key); } private void effect_angle_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) diff --git a/Project-Aurora/Project-Aurora/Profiles/Application.cs b/Project-Aurora/Project-Aurora/Profiles/Application.cs index f6dc1c7d0..b32b26141 100755 --- a/Project-Aurora/Project-Aurora/Profiles/Application.cs +++ b/Project-Aurora/Project-Aurora/Profiles/Application.cs @@ -44,24 +44,10 @@ public class LightEventConfig : NotifyPropertyChangedEx public LightEvent Event { get; set; } - public int? UpdateInterval { get; set; } = null; - public string IconURI { get; set; } public HashSet ExtraAvailableLayers { get; set; } = new HashSet(); - protected LightEventType? type = LightEventType.Normal; - public LightEventType? Type - { - get { return type; } - set - { - object old = type; - object newVal = value; - type = value; - InvokePropertyChanged(old, newVal); - } - } public bool EnableByDefault { get; set; } = true; public bool EnableOverlaysByDefault { get; set; } = true; @@ -84,18 +70,7 @@ public class Application : ObjectSettings, IInit, ILightEve public bool IsEnabled { get { return Settings.IsEnabled; } } public bool IsOverlayEnabled { get { return Settings.IsOverlayEnabled; } } public event PropertyChangedExEventHandler PropertyChanged; - protected LightEventType type; - public LightEventType Type - { - get { return type; } - protected set - { - object old = type; - object newVal = value; - type = value; - InvokePropertyChanged(old, newVal); - } - } + #endregion #region Internal Properties diff --git a/Project-Aurora/Project-Aurora/Profiles/Desktop/Event_Desktop.cs b/Project-Aurora/Project-Aurora/Profiles/Desktop/Event_Desktop.cs index 5cb381ff8..f4d2f7b7c 100755 --- a/Project-Aurora/Project-Aurora/Profiles/Desktop/Event_Desktop.cs +++ b/Project-Aurora/Project-Aurora/Profiles/Desktop/Event_Desktop.cs @@ -25,7 +25,6 @@ public Event_Desktop() : base() public override void UpdateLights(EffectFrame frame) { var layers = new Queue(Application.Profile.Layers.Where(l => l.Enabled).Reverse().Select(l => l.Render(_game_state))); - var overlayLayers = new Queue(Application.Profile.OverlayLayers.Where(l => l.Enabled).Reverse().Select(l => l.Render(_game_state))); //Scripts before interactive and shortcut assistant layers //ProfilesManager.DesktopProfile.UpdateEffectScripts(layers); @@ -43,6 +42,11 @@ public override void UpdateLights(EffectFrame frame) } frame.AddLayers(layers.ToArray()); + } + public override void UpdateOverlayLights(EffectFrame frame) + { + var overlayLayers = new Queue(Application.Profile.OverlayLayers.Where(l => l.Enabled).Reverse().Select(l => l.Render(_game_state))); + frame.AddOverlayLayers(overlayLayers.ToArray()); } diff --git a/Project-Aurora/Project-Aurora/Profiles/LightEvent.cs b/Project-Aurora/Project-Aurora/Profiles/LightEvent.cs index 55c3ef33c..999265a2d 100644 --- a/Project-Aurora/Project-Aurora/Profiles/LightEvent.cs +++ b/Project-Aurora/Project-Aurora/Profiles/LightEvent.cs @@ -8,12 +8,6 @@ namespace Aurora.Profiles { - public enum LightEventType - { - Normal, - Underlay, - Overlay - } public interface ILightEvent : IInit { diff --git a/Project-Aurora/Project-Aurora/Profiles/LightingStateManager.cs b/Project-Aurora/Project-Aurora/Profiles/LightingStateManager.cs index 1ea362aa8..d599b9336 100755 --- a/Project-Aurora/Project-Aurora/Profiles/LightingStateManager.cs +++ b/Project-Aurora/Project-Aurora/Profiles/LightingStateManager.cs @@ -1,101 +1,44 @@ -using Aurora.Profiles.Aurora_Wrapper; -using Aurora.Profiles.Desktop; -using Aurora.Profiles.Generic_Application; +using Aurora.EffectsEngine; using Aurora.Settings; using Aurora.Settings.Layers; using Aurora.Utils; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; +using System.Drawing; using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using System.Text; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using System.Windows; -using System.Windows.Data; -using System.Globalization; namespace Aurora.Profiles { - public class LayerHandlerEntry + public interface ILightingEngine { - public Type Type { get; set; } - - public string Title { get; set; } - - public string Key { get; set; } - - public LayerHandlerEntry(string key, string title, Type type) - { - this.Type = type; - this.Title = title; - this.Key = key; - } - - public override string ToString() - { - return Title; - } - } - - public class ProfilesManagerSettings - { - public ProfilesManagerSettings() - { - - } - - [OnDeserialized] - void OnDeserialized(StreamingContext context) - { - - } + void ActiveProfileChanged(ILightEvent profile); + void RefreshOverLayerProfiles(List profiles); } - public class LightingStateManager : ObjectSettings, IInit + public class LightingStateManager : ILightingEngine, IInit { - public Dictionary Events { get; private set; } = new Dictionary { { "desktop", new Desktop.Desktop() } }; - - public Desktop.Desktop DesktopProfile { get { return (Desktop.Desktop)Events["desktop"]; } } + private ILightEvent ActiveProfile; + private List OverlayProfiles = new List(); - private List Underlays = new List(); - private List Normal = new List(); - private List Overlays = new List(); - - private List StartedEvents = new List(); - private List UpdatedEvents = new List(); - - private Dictionary EventProcesses { get; set; } = new Dictionary(); - - private Dictionary EventTitles { get; set; } = new Dictionary(); - - private Dictionary EventAppIDs { get; set; } = new Dictionary(); + private Timer updateTimer; - public Dictionary LayerHandlers { get; private set; } = new Dictionary(); + private int timerInterval = 33; - public List DefaultLayerHandlers { get; private set; } = new List(); + private long currentTick; - public string AdditionalProfilesPath = Path.Combine(Global.AppDataDirectory, "AdditionalProfiles"); public event EventHandler PreUpdate; public event EventHandler PostUpdate; - private ActiveProcessMonitor processMonitor; - private RunningProcessMonitor runningProcessMonitor; - public RunningProcessMonitor RunningProcessMonitor => runningProcessMonitor; + private List TimedLayers = new List(); - public LightingStateManager() + public LightingStateManager(ILightEvent profile) { - SettingsSavePath = Path.Combine(Global.AppDataDirectory, "ProfilesSettings.json"); + ActiveProfile = profile; } - public bool Initialized { get; private set; } public bool Initialize() @@ -103,398 +46,12 @@ public bool Initialize() if (Initialized) return true; - processMonitor = new ActiveProcessMonitor(); - runningProcessMonitor = new RunningProcessMonitor(); - - #region Initiate Defaults - RegisterEvents(new List { - new Desktop.Desktop(), - new Dota_2.Dota2(), - new CSGO.CSGO(), - new GTA5.GTA5(), - new RocketLeague.RocketLeague(), - new Borderlands2.Borderlands2(), - new Overwatch.Overwatch(), - new Payday_2.PD2(), - new TheDivision.TheDivision(), - new LeagueOfLegends.LoL(), - new HotlineMiami.HotlineMiami(), - new TheTalosPrinciple.TalosPrinciple(), - new BF3.BF3(), - new Blacklight.Blacklight(), - new Magic_Duels_2012.MagicDuels2012(), - new ShadowOfMordor.ShadowOfMordor(), - new Serious_Sam_3.SSam3(), - new DiscoDodgeball.DiscoDodgeballApplication(), - new XCOM.XCOM(), - new Evolve.Evolve(), - new Metro_Last_Light.MetroLL(), - new Guild_Wars_2.GW2(), - new WormsWMD.WormsWMD(), - new Blade_and_Soul.BnS(), - new Skype.Skype(), - new ROTTombRaider.ROTTombRaider(), - new DyingLight.DyingLight(), - new ETS2.ETS2(), - new ATS.ATS(), - new Move_or_Die.MoD(), - new QuantumConumdrum.QuantumConumdrum(), - new Battlefield1.Battlefield1(), - new Dishonored.Dishonored(), - new Witcher3.Witcher3(), - new Minecraft.Minecraft(), - new KillingFloor2.KillingFloor2(), - new DOOM.DOOM(), - new Factorio.Factorio(), - new QuakeChampions.QuakeChampions(), - new Diablo3.Diablo3(), - new DeadCells.DeadCells(), - new Subnautica.Subnautica(), - new ResidentEvil2.ResidentEvil2(), - new CloneHero.CloneHero(), - new Osu.Osu(), - new Slime_Rancher.Slime_Rancher(), - new Terraria.Terraria(), - new Discord.Discord() - }); - - RegisterLayerHandlers(new List { - new LayerHandlerEntry("Default", "Default Layer", typeof(DefaultLayerHandler)), - new LayerHandlerEntry("Solid", "Solid Color Layer", typeof(SolidColorLayerHandler)), - new LayerHandlerEntry("SolidFilled", "Solid Fill Color Layer", typeof(SolidFillLayerHandler)), - new LayerHandlerEntry("Gradient", "Gradient Layer", typeof(GradientLayerHandler)), - new LayerHandlerEntry("GradientFill", "Gradient Fill Layer", typeof(GradientFillLayerHandler)), - new LayerHandlerEntry("Breathing", "Breathing Layer", typeof(BreathingLayerHandler)), - new LayerHandlerEntry("Blinking", "Blinking Layer", typeof(BlinkingLayerHandler)), - new LayerHandlerEntry("Image", "Image Layer", typeof(ImageLayerHandler)), - new LayerHandlerEntry("Script", "Script Layer", typeof(ScriptLayerHandler)), - new LayerHandlerEntry("Percent", "Percent Effect Layer", typeof(PercentLayerHandler)), - new LayerHandlerEntry("PercentGradient", "Percent (Gradient) Effect Layer", typeof(PercentGradientLayerHandler)), - new LayerHandlerEntry("Razer", "Razer Chroma Layer", typeof(RazerLayerHandler)), - new LayerHandlerEntry("Conditional", "Conditional Layer", typeof(ConditionalLayerHandler)), - new LayerHandlerEntry("Comparison", "Comparison Layer", typeof(ComparisonLayerHandler)), - new LayerHandlerEntry("Interactive", "Interactive Layer", typeof(InteractiveLayerHandler) ), - new LayerHandlerEntry("ShortcutAssistant", "Shortcut Assistant Layer", typeof(ShortcutAssistantLayerHandler) ), - new LayerHandlerEntry("Equalizer", "Audio Visualizer Layer", typeof(EqualizerLayerHandler) ), - new LayerHandlerEntry("Ambilight", "Ambilight Layer", typeof(AmbilightLayerHandler) ), - new LayerHandlerEntry("LockColor", "Lock Color Layer", typeof(LockColourLayerHandler) ), - new LayerHandlerEntry("Glitch", "Glitch Effect Layer", typeof(GlitchLayerHandler) ), - new LayerHandlerEntry("Animation", "Animation Layer", typeof(AnimationLayerHandler) ), - new LayerHandlerEntry("ToggleKey", "Toggle Key Layer", typeof(ToggleKeyLayerHandler)), - new LayerHandlerEntry("Timer", "Timer Layer", typeof(TimerLayerHandler)), - new LayerHandlerEntry("Toolbar", "Toolbar Layer", typeof(ToolbarLayerHandler)), - new LayerHandlerEntry("BinaryCounter", "Binary Counter Layer", typeof(BinaryCounterLayerHandler)) - }, true); - - RegisterLayerHandler(new LayerHandlerEntry("WrapperLights", "Wrapper Lighting Layer", typeof(WrapperLightsLayerHandler)), false); - - #endregion - - LoadSettings(); - - this.LoadPlugins(); - - if (Directory.Exists(AdditionalProfilesPath)) - { - List additionals = new List(Directory.EnumerateDirectories(AdditionalProfilesPath)); - foreach (var dir in additionals) - { - if (File.Exists(Path.Combine(dir, "settings.json"))) - { - string proccess_name = Path.GetFileName(dir); - RegisterEvent(new GenericApplication(proccess_name)); - } - } - } - - foreach (var profile in Events) - { - profile.Value.Initialize(); - } - this.InitUpdate(); - // Listen for profile keybind triggers - Global.InputEvents.KeyDown += CheckProfileKeybinds; - Initialized = true; return Initialized; } - private void LoadPlugins() - { - Global.PluginManager.ProcessManager(this); - } - - protected override void LoadSettings(Type settingsType) - { - base.LoadSettings(settingsType); - - foreach (var kvp in Events) - { - if (!Global.Configuration.ProfileOrder.Contains(kvp.Key) && kvp.Value is Application) - Global.Configuration.ProfileOrder.Add(kvp.Key); - } - - foreach(string key in Global.Configuration.ProfileOrder.ToList()) - { - if (!Events.ContainsKey(key) || !(Events[key] is Application)) - Global.Configuration.ProfileOrder.Remove(key); - } - - Global.Configuration.ProfileOrder.Remove("desktop"); - Global.Configuration.ProfileOrder.Insert(0, "desktop"); - } - - public void SaveAll() - { - SaveSettings(); - - foreach(var profile in Events) - { - if (profile.Value is Application) - ((Application)profile.Value).SaveAll(); - } - } - - public bool RegisterProfile(LightEventConfig config) - { - return RegisterEvent(new Application(config)); - } - - private List GetEventTable(LightEventType type) - { - List events; - switch (type) - { - case LightEventType.Normal: - events = Normal; - break; - case LightEventType.Overlay: - events = Overlays; - break; - case LightEventType.Underlay: - events = Underlays; - break; - default: - throw new NotImplementedException(); - } - return events; - } - - private bool InsertLightEvent(ILightEvent lightEvent, LightEventType? old = null) - { - LightEventType type = lightEvent.Config.Type ?? LightEventType.Normal; - lightEvent.Config.Type = type; - - if (old == null) - { - lightEvent.Config.PropertyChanged += LightEvent_PropertyChanged; - } - else - { - var oldEvents = GetEventTable((LightEventType)old); - oldEvents.Remove(lightEvent.Config.ID); - } - - var events = GetEventTable(type); - - events.Add(lightEvent.Config.ID); - - return true; - } - - private void LightEvent_PropertyChanged(object sender, PropertyChangedExEventArgs e) - { - ILightEvent lightEvent = (ILightEvent)sender; - if (e.PropertyName.Equals(nameof(LightEventConfig.Type))) - { - LightEventType old = (LightEventType)e.OldValue; - LightEventType newVal = (LightEventType)e.NewValue; - - if (!old.Equals(newVal)) - { - InsertLightEvent(lightEvent, old); - } - } - } - - public bool RegisterEvent(ILightEvent @event) - { - string key = @event.Config.ID; - if (string.IsNullOrWhiteSpace(key) || Events.ContainsKey(key)) - return false; - - Events.Add(key, @event); - - if (@event.Config.ProcessNames != null) - { - foreach (string exe in @event.Config.ProcessNames) - { - if (!exe.Equals(key)) - EventProcesses.Add(exe.ToLower(), key); - } - } - - if (@event.Config.ProcessTitles != null) - foreach (string titleRx in @event.Config.ProcessTitles) - EventTitles.Add(titleRx, key); - - if (!String.IsNullOrWhiteSpace(@event.Config.AppID)) - EventAppIDs.Add(@event.Config.AppID, key); - - if (@event is Application) - { - if (!Global.Configuration.ProfileOrder.Contains(key)) - Global.Configuration.ProfileOrder.Add(key); - } - - this.InsertLightEvent(@event); - - if (Initialized) - @event.Initialize(); - - return true; - } - - public void RegisterProfiles(List profiles) - { - foreach (var profile in profiles) - { - RegisterProfile(profile); - } - } - - public void RegisterEvents(List profiles) - { - foreach (var profile in profiles) - { - RegisterEvent(profile); - } - } - - public void RemoveGenericProfile(string key) - { - if (Events.ContainsKey(key)) - { - if (!(Events[key] is GenericApplication)) - return; - GenericApplication profile = (GenericApplication)Events[key]; - Events.Remove(key); - Global.Configuration.ProfileOrder.Remove(key); - - profile.Dispose(); - - string path = profile.GetProfileFolderPath(); - if (Directory.Exists(path)) - Directory.Delete(path, true); - - //SaveSettings(); - } - } - - public ILightEvent GetProfileFromProcessName(string process) - { - if (EventProcesses.ContainsKey(process)) - { - if (!Events.ContainsKey(EventProcesses[process])) - Global.logger.Warn($"GetProfileFromProcess: The process '{process}' exists in EventProcesses but subsequently '{EventProcesses[process]}' does not in Events!"); - - return Events[EventProcesses[process]]; - } - else if (Events.ContainsKey(process)) - return Events[process]; - - return null; - } - - public ILightEvent GetProfileFromProcessTitle(string title) { - foreach (var entry in EventTitles) { - if (Regex.IsMatch(title, entry.Key, RegexOptions.IgnoreCase)) { - if (!Events.ContainsKey(entry.Value)) - Global.logger.Warn($"GetProfileFromProcess: The process with title '{title}' matchs an item in EventTitles but subsequently '{entry.Value}' does not in Events!"); - else - return Events[entry.Value]; // added in an else so we keep searching for more valid regexes. - } - } - return null; - } - - public ILightEvent GetProfileFromAppID(string appid) - { - if (EventAppIDs.ContainsKey(appid)) - { - if (!Events.ContainsKey(EventAppIDs[appid])) - Global.logger.Warn($"GetProfileFromAppID: The appid '{appid}' exists in EventAppIDs but subsequently '{EventAppIDs[appid]}' does not in Events!"); - return Events[EventAppIDs[appid]]; - } - else if (Events.ContainsKey(appid)) - return Events[appid]; - - return null; - } - - public void RegisterLayerHandlers(List layers, bool @default = true) - { - foreach(var layer in layers) - { - RegisterLayerHandler(layer, @default); - } - } - - public bool RegisterLayerHandler(LayerHandlerEntry entry, bool @default = true) - { - if (LayerHandlers.ContainsKey(entry.Key) || DefaultLayerHandlers.Contains(entry.Key)) - return false; - - LayerHandlers.Add(entry.Key, entry); - - if (@default) - DefaultLayerHandlers.Add(entry.Key); - - return true; - } - - public bool RegisterLayerHandler(string key, string title, Type type, bool @default = true) - { - return RegisterLayerHandler(new LayerHandlerEntry(key, title, type)); - } - - public Type GetLayerHandlerType(string key) - { - return LayerHandlers.ContainsKey(key) ? LayerHandlers[key].Type : null; - } - - public ILayerHandler GetLayerHandlerInstance(LayerHandlerEntry entry) - { - return (ILayerHandler)Activator.CreateInstance(entry.Type); - } - - public ILayerHandler GetLayerHandlerInstance(string key) - { - if (LayerHandlers.ContainsKey(key)) - { - return GetLayerHandlerInstance(LayerHandlers[key]); - } - - - return null; - } - - private Timer updateTimer; - - private const int defaultTimerInterval = 33; - private int timerInterval = defaultTimerInterval; - - private long nextProcessNameUpdate; - private long currentTick; - private string previewModeProfileKey = ""; - - private List overlays = new List(); - private Event_Idle idle_e = new Event_Idle(); - - public string PreviewProfileKey { get { return previewModeProfileKey; } set { previewModeProfileKey = value ?? string.Empty; } } - private void InitUpdate() { updateTimer = new System.Threading.Timer(g => { @@ -521,203 +78,107 @@ private void InitUpdate() GC.KeepAlive(updateTimer); } - private void UpdateProcess() + private void RefreshLightningFrame() { - if (Global.Configuration.detection_mode == ApplicationDetectionMode.ForegroroundApp && (currentTick >= nextProcessNameUpdate)) + EffectsEngine.EffectFrame newFrame = new EffectsEngine.EffectFrame(); + + if (ActiveProfile.IsEnabled) { - processMonitor.GetActiveWindowsProcessname(); - nextProcessNameUpdate = currentTick + 1000L; + ActiveProfile.UpdateLights(newFrame); } - } - - private void UpdateIdleEffects(EffectsEngine.EffectFrame newFrame) - { - tagLASTINPUTINFO LastInput = new tagLASTINPUTINFO(); - Int32 IdleTime; - LastInput.cbSize = (uint)Marshal.SizeOf(LastInput); - LastInput.dwTime = 0; - - if (ActiveProcessMonitor.GetLastInputInfo(ref LastInput)) + foreach (ILightEvent prof in OverlayProfiles) { - IdleTime = System.Environment.TickCount - LastInput.dwTime; - - if (IdleTime >= Global.Configuration.idle_delay * 60 * 1000) - { - if (!(Global.Configuration.time_based_dimming_enabled && - Utils.Time.IsCurrentTimeBetween(Global.Configuration.time_based_dimming_start_hour, Global.Configuration.time_based_dimming_start_minute, Global.Configuration.time_based_dimming_end_hour, Global.Configuration.time_based_dimming_end_minute)) - ) - { - UpdateEvent(idle_e, newFrame); - } - } + if (prof.IsOverlayEnabled) + prof.UpdateOverlayLights(newFrame); + } + if (ActiveProfile.IsEnabled) + { + ActiveProfile.UpdateOverlayLights(newFrame); } - } - - private void UpdateEvent(ILightEvent @event, EffectsEngine.EffectFrame frame) - { - StartEvent(@event); - @event.UpdateLights(frame); - } - - private bool StartEvent(ILightEvent @event) - { - UpdatedEvents.Add(@event); - - // Skip if event was already started - if (StartedEvents.Contains(@event)) return false; - - StartedEvents.Add(@event); - @event.OnStart(); - return true; - } + var timedLayers = TimedLayers.ToList(); + var layers = new Queue(timedLayers.Select(l => ((Layer)l.item).Render(null))); + newFrame.AddOverlayLayers(layers.ToArray()); - private bool StopUnUpdatedEvents() - { - // Skip if there are no started events or started events are the same since last update - if (!StartedEvents.Any() || StartedEvents.SequenceEqual(UpdatedEvents)) return false; - - List eventsToStop = StartedEvents.Except(UpdatedEvents).ToList(); - foreach (var eventToStop in eventsToStop) - eventToStop.OnStop(); - - StartedEvents.Clear(); - StartedEvents.AddRange(UpdatedEvents); - - return true; + Global.effengine.PushFrame(newFrame); } private void Update() { PreUpdate?.Invoke(this, null); - UpdatedEvents.Clear(); //Blackout. TODO: Cleanup this a bit. Maybe push blank effect frame to keyboard incase it has existing stuff displayed if ((Global.Configuration.time_based_dimming_enabled && Utils.Time.IsCurrentTimeBetween(Global.Configuration.time_based_dimming_start_hour, Global.Configuration.time_based_dimming_start_minute, Global.Configuration.time_based_dimming_end_hour, Global.Configuration.time_based_dimming_end_minute))) { - StopUnUpdatedEvents(); return; } - string raw_process_name = Path.GetFileName(processMonitor.ProcessPath); - - UpdateProcess(); - EffectsEngine.EffectFrame newFrame = new EffectsEngine.EffectFrame(); + Global.dev_manager.InitializeOnce(); + timerInterval = 1000 / Global.Configuration.FrameRate; - //TODO: Move these IdleEffects to an event - //this.UpdateIdleEffects(newFrame); - - ILightEvent profile = GetCurrentProfile(out bool preview); + RefreshLightningFrame(); - timerInterval = profile?.Config?.UpdateInterval ?? defaultTimerInterval; - - // If the current foreground process is excluded from Aurora, disable the lighting manager - if ((profile is Desktop.Desktop && !profile.IsEnabled) || Global.Configuration.excluded_programs.Contains(raw_process_name)) - { - StopUnUpdatedEvents(); - Global.dev_manager.Shutdown(); - Global.effengine.PushFrame(newFrame); - return; - } - else - Global.dev_manager.InitializeOnce(); - - if (Global.Configuration.OverlaysInPreview || !preview) - { - foreach (var underlay in Underlays) - { - ILightEvent @event = Events[underlay]; - if (@event.IsEnabled && (@event.Config.ProcessNames == null || ProcessUtils.AnyProcessExists(@event.Config.ProcessNames))) - UpdateEvent(@event, newFrame); - } - } + PostUpdate?.Invoke(this, null); + } - //Need to do another check in case Desktop is disabled or the selected preview is disabled - if (profile.IsEnabled) - UpdateEvent(profile, newFrame); + public void Dispose() + { + updateTimer.Dispose(); + updateTimer = null; + } - if (Global.Configuration.OverlaysInPreview || !preview) + public void ActiveProfileChanged(ILightEvent profile) + { + if (Global.Configuration.ProfileChangeAnimation) { - // Update any overlays registered in the Overlays array. This includes applications with type set to Overlay and things such as skype overlay - foreach (var overlay in Overlays) + AddOverlayForDuration(new Layer("Profile Close Helper Layer", new GradientFillLayerHandler() { - ILightEvent @event = Events[overlay]; - if (@event.IsEnabled && (@event.Config.ProcessNames == null || ProcessUtils.AnyProcessExists(@event.Config.ProcessNames))) - UpdateEvent(@event, newFrame); - } + Properties = new GradientFillLayerHandlerProperties() + { + _FillEntireKeyboard = true, + _GradientConfig = new LayerEffectConfig(Color.FromArgb(0, 0, 0, 0), Color.FromArgb(255, 0, 0, 0)) { AnimationType = AnimationType.Translate_XY, speed = 10 } - // Update any overlays that are timer-based (e.g. the volume overlay that appears for a few seconds at a time) - TimedListObject[] overlay_events = overlays.ToArray(); - foreach (TimedListObject evnt in overlay_events) + } + }), 600); + Task.Factory.StartNew(() => { - if ((evnt.item as LightEvent).IsEnabled) - UpdateEvent((evnt.item as LightEvent), newFrame); - } + Thread.Sleep(450); - // Update any applications that have overlay layers if that application is open - var events = GetOverlayActiveProfiles().ToList(); - - //Add the Light event that we're previewing to be rendered as an overlay - if (preview && Global.Configuration.OverlaysInPreview && !events.Contains(profile)) - events.Add(profile); + ActiveProfile = profile; + AddOverlayForDuration(new Layer("Profile Open Helper Layer", new GradientFillLayerHandler() + { + Properties = new GradientFillLayerHandlerProperties() + { + _FillEntireKeyboard = true, + _GradientConfig = new LayerEffectConfig(Color.FromArgb(255, 0, 0, 0), Color.FromArgb(0, 0, 0, 0)) { AnimationType = AnimationType.Translate_XY, speed = 10 } + } + }), 900); - foreach (var @event in events) - @event.UpdateOverlayLights(newFrame); - - UpdateIdleEffects(newFrame); + }); } - - Global.effengine.PushFrame(newFrame); - - StopUnUpdatedEvents(); - PostUpdate?.Invoke(this, null); - } - - /// Gets the current application. - /// Boolean indicating whether the application is selected because it is previewing (true) or because the process is open (false). - public ILightEvent GetCurrentProfile(out bool preview) { - string process_name = Path.GetFileName(processMonitor.ProcessPath).ToLower(); - string process_title = processMonitor.GetActiveWindowsProcessTitle(); - ILightEvent profile = null; - ILightEvent tempProfile = null; - preview = false; - - //TODO: GetProfile that checks based on event type - if ((((tempProfile = GetProfileFromProcessName(process_name)) != null) || ((tempProfile = GetProfileFromProcessTitle(process_title)) != null)) && tempProfile.Config.Type == LightEventType.Normal && tempProfile.IsEnabled) - profile = tempProfile; - else if ((tempProfile = GetProfileFromProcessName(previewModeProfileKey)) != null) //Don't check for it being Enabled as a preview should always end-up with the previewed profile regardless of it being disabled + else { - profile = tempProfile; - preview = true; - } else if (Global.Configuration.allow_wrappers_in_background && Global.net_listener != null && Global.net_listener.IsWrapperConnected && ((tempProfile = GetProfileFromProcessName(Global.net_listener.WrappedProcess)) != null) && tempProfile.Config.Type == LightEventType.Normal && tempProfile.IsEnabled) - profile = tempProfile; - - profile = profile ?? DesktopProfile; + ActiveProfile = profile; + } + } - return profile; + public void RefreshOverLayerProfiles(List profiles) + { + OverlayProfiles = profiles; } - /// Gets the current application. - public ILightEvent GetCurrentProfile() => GetCurrentProfile(out bool _); - - /// - /// Returns a list of all profiles that should have their overlays active. This will include processes that running but not in the foreground. - /// - /// - public IEnumerable GetOverlayActiveProfiles() => Events.Values - .Where(evt => evt.IsOverlayEnabled) - .Where(evt => evt.Config.ProcessNames == null || evt.Config.ProcessNames.Any(name => runningProcessMonitor.IsProcessRunning(name))); - //.Where(evt => evt.Config.ProcessTitles == null || ProcessUtils.AnyProcessWithTitleExists(evt.Config.ProcessTitles)); /// KeyDown handler that checks the current application's profiles for keybinds. /// In the case of multiple profiles matching the keybind, it will pick the next one as specified in the Application.Profile order. - public void CheckProfileKeybinds(object sender, SharpDX.RawInput.KeyboardInputEventArgs e) { - ILightEvent profile = GetCurrentProfile(); + public void CheckProfileKeybinds(object sender, SharpDX.RawInput.KeyboardInputEventArgs e) + { + ILightEvent profile = ActiveProfile; // Check profile is valid and do not switch profiles if the user is trying to enter a keybind - if (profile is Application && Controls.Control_Keybind._ActiveKeybind == null) { + if (profile is Application && Controls.Control_Keybind._ActiveKeybind == null) + { // Find all profiles that have their keybinds pressed List possibleProfiles = new List(); @@ -726,113 +187,18 @@ public void CheckProfileKeybinds(object sender, SharpDX.RawInput.KeyboardInputEv possibleProfiles.Add(prof); // If atleast one profile has it's key pressed - if (possibleProfiles.Count > 0) { + if (possibleProfiles.Count > 0) + { // The target profile is the NEXT valid profile after the currently selected one (or the first valid one if the currently selected one doesn't share this keybind) int trg = (possibleProfiles.IndexOf((profile as Application).Profile) + 1) % possibleProfiles.Count; (profile as Application).SwitchToProfile(possibleProfiles[trg]); } } } - - - public void GameStateUpdate(IGameState gs) - { - //Debug.WriteLine("Received gs!"); - -//Global.logger.LogLine(gs.ToString(), Logging_Level.None, false); - -//UpdateProcess(); - -//string process_name = System.IO.Path.GetFileName(processMonitor.ProcessPath).ToLowerInvariant(); - -//EffectsEngine.EffectFrame newFrame = new EffectsEngine.EffectFrame(); -#if DEBUG -#else - try - { -#endif - ILightEvent profile;// = this.GetProfileFromProcess(process_name); - - - JObject provider = Newtonsoft.Json.Linq.JObject.Parse(gs.GetNode("provider")); - string appid = provider.GetValue("appid").ToString(); - string name = provider.GetValue("name").ToString().ToLowerInvariant(); - - if ((profile = GetProfileFromAppID(appid)) != null || (profile = GetProfileFromProcessName(name)) != null) - { - IGameState gameState = gs; - if (profile.Config.GameStateType != null) - gameState = (IGameState)Activator.CreateInstance(profile.Config.GameStateType, gs.json); - profile.SetGameState(gameState); - } - else if (gs is GameState_Wrapper && Global.Configuration.allow_all_logitech_bitmaps) - { - string gs_process_name = Newtonsoft.Json.Linq.JObject.Parse(gs.GetNode("provider")).GetValue("name").ToString().ToLowerInvariant(); - lock (Events) - { - profile = profile ?? GetProfileFromProcessName(gs_process_name); - - if (profile == null) - { - Events.Add(gs_process_name, new GameEvent_Aurora_Wrapper(new LightEventConfig { GameStateType = typeof(GameState_Wrapper), ProcessNames = new[] { gs_process_name } })); - profile = Events[gs_process_name]; - } - - profile.SetGameState(gs); - } - } -#if DEBUG -#else - } - catch (Exception e) - { - Global.logger.LogLine("Exception during GameStateUpdate(), error: " + e, Logging_Level.Warning); - } -#endif - } - - public void ResetGameState(string process) + public void AddOverlayForDuration(Layer overlay_event, int duration) { - ILightEvent profile; - if (((profile = GetProfileFromProcessName(process)) != null)) - profile.ResetGameState(); + TimedLayers.Add(new TimedListObject(overlay_event, duration, TimedLayers)); } - public void AddOverlayForDuration(LightEvent overlay_event, int duration, bool isUnique = true) - { - if (isUnique) - { - TimedListObject[] overlays_array = overlays.ToArray(); - bool isFound = false; - - foreach (TimedListObject obj in overlays_array) - { - if (obj.item.GetType() == overlay_event.GetType()) - { - isFound = true; - obj.AdjustDuration(duration); - break; - } - } - - if (!isFound) - { - overlays.Add(new TimedListObject(overlay_event, duration, overlays)); - } - } - else - { - overlays.Add(new TimedListObject(overlay_event, duration, overlays)); - } - } - - public void Dispose() - { - updateTimer.Dispose(); - updateTimer = null; - - foreach (var app in this.Events) - app.Value.Dispose(); - } } } diff --git a/Project-Aurora/Project-Aurora/Profiles/ProcessManager.cs b/Project-Aurora/Project-Aurora/Profiles/ProcessManager.cs new file mode 100644 index 000000000..ede81feac --- /dev/null +++ b/Project-Aurora/Project-Aurora/Profiles/ProcessManager.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; +using System.Globalization; +using Aurora.Utils; +using Aurora.Settings; + +namespace Aurora.Profiles +{ + public interface IProcessChanged + { + void ActiveProcessChanged(string key); + void OpenBackgroundProcess(string key); + void CloseBackgroundProcess(string key); + } + public class ProcessManager + { + + private static readonly int SleepTime = 3000; + private static bool IsExit = false; + private static Dictionary EventProcesses { get; set; } = new Dictionary(); + private static Dictionary EventTitles { get; set; } = new Dictionary(); + private static string PreviousActiveProcess = ""; + private static List RunningBackgroundProcess = new List(); + + private static ActiveProcessMonitor ProcessMonitor; + private static IProcessChanged Listener; + + public ProcessManager() + { + + } + + public ProcessManager(IProcessChanged listener) + { + Listener = listener; + ProcessMonitor = new ActiveProcessMonitor(); + } + + + public void SubsribeForChange(string key, string[] processNames, string[] processTitles) + { + //Global.logger.LogLine("ProcessManager::SubsribeForChange()" + key); + if (processNames != null) + { + foreach (string exe in processNames) + { + //if (!exe.Equals(key)) + EventProcesses.Add(exe.ToLower(), key); + } + } + if (processTitles != null) + foreach (string titleRx in processTitles) + EventTitles.Add(titleRx, key); + } + public void Start() + { + IsExit = false; + Thread thread1 = new Thread(UpdateActiveProcess); + Thread thread2 = new Thread(UpdateBackgroundProcess); + thread1.Start(); + thread2.Start(); + } + public void Finish() + { + //Global.logger.LogLine("ProcessManager::Finished()"); + IsExit = true; + } + + + private static void UpdateActiveProcess() + { + while (!IsExit) + { + if (Global.Configuration.detection_mode == ApplicationDetectionMode.ForegroroundApp) + { + ProcessMonitor.GetActiveWindowsProcessname(); + string process_name = Path.GetFileName(ProcessMonitor.ProcessPath).ToLower(); + string process_title = ProcessMonitor.GetActiveWindowsProcessTitle(); + + //(Global.Configuration.allow_wrappers_in_background && Global.net_listener != null && Global.net_listener.IsWrapperConnected && ((tempProfile = GetProfileFromProcessName(Global.net_listener.WrappedProcess)) != null) && tempProfile.Config.Type == LightEventType.Normal && tempProfile.IsEnabled) + if (EventProcesses.ContainsKey(process_name) || EventTitles.Where(title => Regex.IsMatch(process_title, title.Key, RegexOptions.IgnoreCase)).Any()) + { + if (process_name != PreviousActiveProcess) + { + Listener.ActiveProcessChanged(EventProcesses[process_name]); + PreviousActiveProcess = process_name; + } + } + else + { + if (PreviousActiveProcess != string.Empty) + { + PreviousActiveProcess = string.Empty; + Listener.ActiveProcessChanged(null); + } + } + } + Thread.Sleep(SleepTime); + } + + } + private void UpdateBackgroundProcess() + { + while (!IsExit) + { + foreach (var process in EventProcesses) + { + if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(process.Key)).Length > 0) + { + if (!RunningBackgroundProcess.Contains(process.Value)) + { + RunningBackgroundProcess.Add(process.Value); + Listener.OpenBackgroundProcess(process.Value); + } + } + else + { + if (RunningBackgroundProcess.Contains(process.Value)) + { + RunningBackgroundProcess.Remove(process.Value); + Listener.CloseBackgroundProcess(process.Value); + } + } + } + Thread.Sleep(SleepTime); + } + + } + } +} + diff --git a/Project-Aurora/Project-Aurora/Profiles/ProfileManager.cs b/Project-Aurora/Project-Aurora/Profiles/ProfileManager.cs new file mode 100644 index 000000000..bfc625659 --- /dev/null +++ b/Project-Aurora/Project-Aurora/Profiles/ProfileManager.cs @@ -0,0 +1,555 @@ +using Aurora.Profiles.Aurora_Wrapper; +using Aurora.Profiles.Desktop; +using Aurora.Profiles.Generic_Application; +using Aurora.Settings; +using Aurora.Settings.Layers; +using Aurora.Utils; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Data; +using System.Globalization; + +namespace Aurora.Profiles +{ + public class LayerHandlerEntry + { + public Type Type { get; set; } + + public string Title { get; set; } + + public string Key { get; set; } + + public LayerHandlerEntry(string key, string title, Type type) + { + this.Type = type; + this.Title = title; + this.Key = key; + } + + public override string ToString() + { + return Title; + } + } + + public class ProfilesManagerSettings + { + public ProfilesManagerSettings() + { + + } + + [OnDeserialized] + void OnDeserialized(StreamingContext context) + { + + } + } + + public class ProfileManager : ObjectSettings, IInit, IProcessChanged + { + + private ProcessManager ProcessManager; + public LightingStateManager LightingStateManager; + + public Dictionary Events { get; private set; } = new Dictionary { { DesktopProfileName, new Desktop.Desktop() } }; + + public Dictionary LayerHandlers { get; private set; } = new Dictionary(); + public List DefaultLayerHandlers { get; private set; } = new List(); + + public Desktop.Desktop DesktopProfile { get { return (Desktop.Desktop)Events[DesktopProfileName]; } } + + private List BackgroundProfile = new List(); + private string CurrentProfile = DesktopProfileName; + private bool PreviewMode = false; + private const string DesktopProfileName = "desktop"; + + private Dictionary EventProcesses { get; set; } = new Dictionary(); + private Dictionary EventAppIDs { get; set; } = new Dictionary(); + public string AdditionalProfilesPath = Path.Combine(Global.AppDataDirectory, "AdditionalProfiles"); + + + public ProfileManager() + { + Global.logger.LogLine("ProfileManager::ProfileManager()"); + SettingsSavePath = Path.Combine(Global.AppDataDirectory, "ProfilesSettings.json"); + ProcessManager = new ProcessManager(this); + LightingStateManager = new LightingStateManager(DesktopProfile); + } + public bool Initialized { get; private set; } + + public bool Initialize() + { + if (Initialized) + return true; + + #region Initiate Defaults + RegisterEvents(new List { + new Desktop.Desktop(), + new Dota_2.Dota2(), + new CSGO.CSGO(), + new GTA5.GTA5(), + new RocketLeague.RocketLeague(), + new Borderlands2.Borderlands2(), + new Overwatch.Overwatch(), + new Payday_2.PD2(), + new TheDivision.TheDivision(), + new LeagueOfLegends.LoL(), + new HotlineMiami.HotlineMiami(), + new TheTalosPrinciple.TalosPrinciple(), + new BF3.BF3(), + new Blacklight.Blacklight(), + new Magic_Duels_2012.MagicDuels2012(), + new ShadowOfMordor.ShadowOfMordor(), + new Serious_Sam_3.SSam3(), + new DiscoDodgeball.DiscoDodgeballApplication(), + new XCOM.XCOM(), + new Evolve.Evolve(), + new Metro_Last_Light.MetroLL(), + new Guild_Wars_2.GW2(), + new WormsWMD.WormsWMD(), + new Blade_and_Soul.BnS(), + new Skype.Skype(), + new ROTTombRaider.ROTTombRaider(), + new DyingLight.DyingLight(), + new ETS2.ETS2(), + new ATS.ATS(), + new Move_or_Die.MoD(), + new QuantumConumdrum.QuantumConumdrum(), + new Battlefield1.Battlefield1(), + new Dishonored.Dishonored(), + new Witcher3.Witcher3(), + new Minecraft.Minecraft(), + new KillingFloor2.KillingFloor2(), + new DOOM.DOOM(), + new Factorio.Factorio(), + new QuakeChampions.QuakeChampions(), + new Diablo3.Diablo3(), + new DeadCells.DeadCells(), + new Subnautica.Subnautica(), + new ResidentEvil2.ResidentEvil2(), + new CloneHero.CloneHero(), + new Osu.Osu(), + new Slime_Rancher.Slime_Rancher(), + new Terraria.Terraria(), + new Discord.Discord() + }); + + RegisterLayerHandlers(new List { + new LayerHandlerEntry("Default", "Default Layer", typeof(DefaultLayerHandler)), + new LayerHandlerEntry("Solid", "Solid Color Layer", typeof(SolidColorLayerHandler)), + new LayerHandlerEntry("SolidFilled", "Solid Fill Color Layer", typeof(SolidFillLayerHandler)), + new LayerHandlerEntry("Gradient", "Gradient Layer", typeof(GradientLayerHandler)), + new LayerHandlerEntry("GradientFill", "Gradient Fill Layer", typeof(GradientFillLayerHandler)), + new LayerHandlerEntry("Breathing", "Breathing Layer", typeof(BreathingLayerHandler)), + new LayerHandlerEntry("Blinking", "Blinking Layer", typeof(BlinkingLayerHandler)), + new LayerHandlerEntry("Image", "Image Layer", typeof(ImageLayerHandler)), + new LayerHandlerEntry("Script", "Script Layer", typeof(ScriptLayerHandler)), + new LayerHandlerEntry("Percent", "Percent Effect Layer", typeof(PercentLayerHandler)), + new LayerHandlerEntry("PercentGradient", "Percent (Gradient) Effect Layer", typeof(PercentGradientLayerHandler)), + new LayerHandlerEntry("Razer", "Razer Chroma Layer", typeof(RazerLayerHandler)), + new LayerHandlerEntry("Conditional", "Conditional Layer", typeof(ConditionalLayerHandler)), + new LayerHandlerEntry("Comparison", "Comparison Layer", typeof(ComparisonLayerHandler)), + new LayerHandlerEntry("Interactive", "Interactive Layer", typeof(InteractiveLayerHandler) ), + new LayerHandlerEntry("ShortcutAssistant", "Shortcut Assistant Layer", typeof(ShortcutAssistantLayerHandler) ), + new LayerHandlerEntry("Equalizer", "Audio Visualizer Layer", typeof(EqualizerLayerHandler) ), + new LayerHandlerEntry("Ambilight", "Ambilight Layer", typeof(AmbilightLayerHandler) ), + new LayerHandlerEntry("LockColor", "Lock Color Layer", typeof(LockColourLayerHandler) ), + new LayerHandlerEntry("Glitch", "Glitch Effect Layer", typeof(GlitchLayerHandler) ), + new LayerHandlerEntry("Animation", "Animation Layer", typeof(AnimationLayerHandler) ), + new LayerHandlerEntry("ToggleKey", "Toggle Key Layer", typeof(ToggleKeyLayerHandler)), + new LayerHandlerEntry("Timer", "Timer Layer", typeof(TimerLayerHandler)), + new LayerHandlerEntry("Toolbar", "Toolbar Layer", typeof(ToolbarLayerHandler)), + new LayerHandlerEntry("BinaryCounter", "Binary Counter Layer", typeof(BinaryCounterLayerHandler)) + }, true); + + RegisterLayerHandler(new LayerHandlerEntry("WrapperLights", "Wrapper Lighting Layer", typeof(WrapperLightsLayerHandler)), false); + + #endregion + + LoadSettings(); + + this.LoadPlugins(); + + if (Directory.Exists(AdditionalProfilesPath)) + { + List additionals = new List(Directory.EnumerateDirectories(AdditionalProfilesPath)); + foreach (var dir in additionals) + { + if (File.Exists(Path.Combine(dir, "settings.json"))) + { + string proccess_name = Path.GetFileName(dir); + RegisterEvent(new GenericApplication(proccess_name)); + } + } + } + + foreach (var profile in Events) + { + profile.Value.Initialize(); + } + + LightingStateManager.Initialize(); + OpenBackgroundProcess(DesktopProfileName); + + // Listen for profile keybind triggers + Global.InputEvents.KeyDown += LightingStateManager.CheckProfileKeybinds; + + //Global.logger.LogLine("ProcessManager::Start()"); + ProcessManager.Start(); + + Initialized = true; + return Initialized; + } + + private void LoadPlugins() + { + Global.PluginManager.ProcessManager(this); + } + + protected override void LoadSettings(Type settingsType) + { + base.LoadSettings(settingsType); + + foreach (var kvp in Events) + { + if (!Global.Configuration.ProfileOrder.Contains(kvp.Key) && kvp.Value is Application) + Global.Configuration.ProfileOrder.Add(kvp.Key); + } + + foreach (string key in Global.Configuration.ProfileOrder.ToList()) + { + if (!Events.ContainsKey(key) || !(Events[key] is Application)) + Global.Configuration.ProfileOrder.Remove(key); + } + + Global.Configuration.ProfileOrder.Remove(DesktopProfileName); + Global.Configuration.ProfileOrder.Insert(0, DesktopProfileName); + } + + public void SaveAll() + { + SaveSettings(); + + foreach (var profile in Events) + { + if (profile.Value is Application) + ((Application)profile.Value).SaveAll(); + } + } + + public bool RegisterProfile(LightEventConfig config) + { + return RegisterEvent(new Application(config)); + } + + public bool RegisterEvent(ILightEvent @event) + { + string key = @event.Config.ID; + if (string.IsNullOrWhiteSpace(key) || Events.ContainsKey(key)) + return false; + + Events.Add(key, @event); + + Global.logger.LogLine("ProcessManager::RegisterEvent()" + key); + ProcessManager.SubsribeForChange(key, @event.Config.ProcessNames, @event.Config.ProcessTitles); + + if (@event.Config.ProcessNames != null) + { + foreach (string exe in @event.Config.ProcessNames) + { + if (!exe.Equals(key)) + EventProcesses.Add(exe.ToLower(), key); + } + } + + if (!String.IsNullOrWhiteSpace(@event.Config.AppID)) + EventAppIDs.Add(@event.Config.AppID, key); + + if (@event is Application) + { + if (!Global.Configuration.ProfileOrder.Contains(key)) + Global.Configuration.ProfileOrder.Add(key); + } + + if (Initialized) + @event.Initialize(); + + return true; + } + + public void RegisterProfiles(List profiles) + { + foreach (var profile in profiles) + { + RegisterProfile(profile); + } + } + + public void RegisterEvents(List profiles) + { + foreach (var profile in profiles) + { + RegisterEvent(profile); + } + } + + public void RemoveGenericProfile(string key) + { + if (Events.ContainsKey(key)) + { + if (!(Events[key] is GenericApplication)) + return; + GenericApplication profile = (GenericApplication)Events[key]; + Events.Remove(key); + Global.Configuration.ProfileOrder.Remove(key); + + profile.Dispose(); + + string path = profile.GetProfileFolderPath(); + if (Directory.Exists(path)) + Directory.Delete(path, true); + + //SaveSettings(); + } + } + public void RegisterLayerHandlers(List layers, bool @default = true) + { + foreach (var layer in layers) + { + RegisterLayerHandler(layer, @default); + } + } + + public bool RegisterLayerHandler(LayerHandlerEntry entry, bool @default = true) + { + if (LayerHandlers.ContainsKey(entry.Key) || DefaultLayerHandlers.Contains(entry.Key)) + return false; + + LayerHandlers.Add(entry.Key, entry); + + if (@default) + DefaultLayerHandlers.Add(entry.Key); + + return true; + } + + public bool RegisterLayerHandler(string key, string title, Type type, bool @default = true) + { + return RegisterLayerHandler(new LayerHandlerEntry(key, title, type)); + } + + public Type GetLayerHandlerType(string key) + { + return LayerHandlers.ContainsKey(key) ? LayerHandlers[key].Type : null; + } + + public ILayerHandler GetLayerHandlerInstance(LayerHandlerEntry entry) + { + return (ILayerHandler)Activator.CreateInstance(entry.Type); + } + + public ILayerHandler GetLayerHandlerInstance(string key) + { + if (LayerHandlers.ContainsKey(key)) + { + return GetLayerHandlerInstance(LayerHandlers[key]); + } + + + return null; + } + + + public ILightEvent GetProfileFromProcessName(string process) + { + if (EventProcesses.ContainsKey(process)) + { + if (!Events.ContainsKey(EventProcesses[process])) + Global.logger.Warn($"GetProfileFromProcess: The process '{process}' exists in EventProcesses but subsequently '{EventProcesses[process]}' does not in Events!"); + + return Events[EventProcesses[process]]; + } + else if (Events.ContainsKey(process)) + return Events[process]; + + return null; + } + + public ILightEvent GetProfileFromAppID(string appid) + { + if (EventAppIDs.ContainsKey(appid)) + { + if (!Events.ContainsKey(EventAppIDs[appid])) + Global.logger.Warn($"GetProfileFromAppID: The appid '{appid}' exists in EventAppIDs but subsequently '{EventAppIDs[appid]}' does not in Events!"); + return Events[EventAppIDs[appid]]; + } + else if (Events.ContainsKey(appid)) + return Events[appid]; + + return null; + } + + public void GameStateUpdate(IGameState gs) + { + //Debug.WriteLine("Received gs!"); + + //Global.logger.LogLine(gs.ToString(), Logging_Level.None, false); + + //UpdateProcess(); + + //string process_name = System.IO.Path.GetFileName(processMonitor.ProcessPath).ToLowerInvariant(); + + //EffectsEngine.EffectFrame newFrame = new EffectsEngine.EffectFrame(); +#if DEBUG +#else + try + { +#endif + ILightEvent profile;// = this.GetProfileFromProcess(process_name); + + + JObject provider = Newtonsoft.Json.Linq.JObject.Parse(gs.GetNode("provider")); + string appid = provider.GetValue("appid").ToString(); + string name = provider.GetValue("name").ToString().ToLowerInvariant(); + + if ((profile = GetProfileFromAppID(appid)) != null || (profile = GetProfileFromProcessName(name)) != null) + { + IGameState gameState = gs; + if (profile.Config.GameStateType != null) + gameState = (IGameState)Activator.CreateInstance(profile.Config.GameStateType, gs.json); + profile.SetGameState(gameState); + } + else if (gs is GameState_Wrapper && Global.Configuration.allow_all_logitech_bitmaps) + { + string gs_process_name = Newtonsoft.Json.Linq.JObject.Parse(gs.GetNode("provider")).GetValue("name").ToString().ToLowerInvariant(); + lock (Events) + { + profile = profile ?? GetProfileFromProcessName(gs_process_name); + + if (profile == null) + { + Events.Add(gs_process_name, new GameEvent_Aurora_Wrapper(new LightEventConfig { GameStateType = typeof(GameState_Wrapper), ProcessNames = new[] { gs_process_name } })); + profile = Events[gs_process_name]; + } + + profile.SetGameState(gs); + } + } +#if DEBUG +#else + } + catch (Exception e) + { + Global.logger.LogLine("Exception during GameStateUpdate(), error: " + e, Logging_Level.Warning); + } +#endif + } + + public void ResetGameState(string process) + { + ILightEvent profile; + if (((profile = GetProfileFromProcessName(process)) != null)) + profile.ResetGameState(); + } + + public void Dispose() + { + ProcessManager.Finish(); + LightingStateManager.Dispose(); + + foreach (var app in this.Events) + app.Value.Dispose(); + } + + public void FocusedApplicationChanged(string key) + { + //Global.logger.LogLine("Focused:FocusedApplicationChanged" + key); + if (key == null) + { + LightingStateManager.ActiveProfileChanged(Events[CurrentProfile]); + PreviewMode = false; + } + else + { + LightingStateManager.ActiveProfileChanged(Events[key]); + PreviewMode = true; + } + + } + + + public void ActiveProcessChanged(string key) + { + key = key ?? DesktopProfileName; + //Global.logger.LogLine("Focused:ActiveProcessChanged" + key); + + if (Global.Configuration.excluded_programs.Contains(key)) + { + return; + } + CurrentProfile = Events.Keys.Contains(key) ? key : DesktopProfileName; + + if (Events[CurrentProfile].IsEnabled) + { + LightingStateManager.ActiveProfileChanged(Events[CurrentProfile]); + } + else + { + LightingStateManager.ActiveProfileChanged(Events[DesktopProfileName]); + } + + //(Global.Configuration.allow_wrappers_in_background && Global.net_listener != null && Global.net_listener.IsWrapperConnected && ((tempProfile = GetProfileFromProcessName(Global.net_listener.WrappedProcess)) != null) && tempProfile.Config.Type == LightEventType.Normal && tempProfile.IsEnabled) + } + + public void OpenBackgroundProcess(string key) + { + //Global.logger.LogLine("Focused:OpenBackgroundProcess" + key); + if (Global.Configuration.excluded_programs.Contains(key)) + { + return; + } + BackgroundProfile.Add(key); + Events[key].OnStart(); + RefreshBackroundProfile(); + } + + public void CloseBackgroundProcess(string key) + { + //Global.logger.LogLine("Focused:CloseBackgroundProcess" + key); + if (Global.Configuration.excluded_programs.Contains(key)) + { + return; + } + BackgroundProfile.Remove(key); + Events[key].OnStop(); + RefreshBackroundProfile(); + } + + private void RefreshBackroundProfile() + { + if (Global.Configuration.OverlaysInPreview || PreviewMode) + { + LightingStateManager.RefreshOverLayerProfiles(Events.Values.Where(p => BackgroundProfile.Contains(p.Config.ID) && p.IsOverlayEnabled).ToList()); + } + else + { + List defaultOverlayerProfile = DesktopProfile.IsOverlayEnabled ? new List { DesktopProfile } : new List(); + LightingStateManager.RefreshOverLayerProfiles(defaultOverlayerProfile); + } + } + } +} + diff --git a/Project-Aurora/Project-Aurora/Project-Aurora.csproj b/Project-Aurora/Project-Aurora/Project-Aurora.csproj index 3eea7f48a..7b4cf0a33 100644 --- a/Project-Aurora/Project-Aurora/Project-Aurora.csproj +++ b/Project-Aurora/Project-Aurora/Project-Aurora.csproj @@ -399,6 +399,8 @@ + + diff --git a/Project-Aurora/Project-Aurora/Settings/Configuration.cs b/Project-Aurora/Project-Aurora/Settings/Configuration.cs index 3fa3196c2..47325ac9d 100755 --- a/Project-Aurora/Project-Aurora/Settings/Configuration.cs +++ b/Project-Aurora/Project-Aurora/Settings/Configuration.cs @@ -435,6 +435,8 @@ public class Configuration : Settings public bool unified_hid_disabled = false; public HashSet devices_disabled; public bool OverlaysInPreview; + public int FrameRate; + public bool ProfileChangeAnimation; //Blackout and Night theme public bool time_based_dimming_enabled; @@ -508,6 +510,9 @@ public Configuration() devices_disabled.Add(typeof(Devices.AtmoOrbDevice.AtmoOrbDevice)); devices_disabled.Add(typeof(Devices.NZXT.NZXTDevice)); OverlaysInPreview = false; + FrameRate = 30; + ProfileChangeAnimation = true; + //Blackout and Night theme time_based_dimming_enabled = false; diff --git a/Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml b/Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml index 7efdcd715..f796812d3 100755 --- a/Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml +++ b/Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml @@ -171,6 +171,11 @@ + + + + + diff --git a/Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml.cs b/Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml.cs index f7520957e..baac1544f 100755 --- a/Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml.cs +++ b/Project-Aurora/Project-Aurora/Settings/Control_Settings.xaml.cs @@ -112,6 +112,9 @@ public Control_Settings() this.nighttime_end_hour_updown.Value = Global.Configuration.nighttime_end_hour; this.nighttime_end_minute_updown.Value = Global.Configuration.nighttime_end_minute; + this.frame_rate_updown.Value = Global.Configuration.FrameRate; + this.profile_change_animation_Checkbox.IsChecked = Global.Configuration.ProfileChangeAnimation; + this.idle_effects_type.SelectedIndex = (int)Global.Configuration.idle_type; this.idle_effects_delay.Value = Global.Configuration.idle_delay; this.idle_effects_primary_color_colorpicker.SelectedColor = Utils.ColorUtils.DrawingColorToMediaColor(Global.Configuration.idle_effect_primary_color); @@ -1060,5 +1063,14 @@ private void startDelayAmount_ValueChanged(object sender, RoutedPropertyChangedE } } } + private void chkProfileChangeAnimation_IsCheckedChanged(object sender, RoutedEventArgs e) + { + Global.Configuration.ProfileChangeAnimation = (bool)((CheckBox) sender).IsChecked; + } + private void frame_rate_updown_ValueChanged(object sender, RoutedEventArgs e) + { + Global.Configuration.FrameRate = (int)((IntegerUpDown)sender).Value; + Process.GetCurrentProcess().PriorityClass = Global.Configuration.HighPriority ? ProcessPriorityClass.High : ProcessPriorityClass.Normal; + } } } diff --git a/Project-Aurora/Project-Aurora/Settings/KeyboardLayoutManager.cs b/Project-Aurora/Project-Aurora/Settings/KeyboardLayoutManager.cs index fc79853c8..fc4aead5d 100755 --- a/Project-Aurora/Project-Aurora/Settings/KeyboardLayoutManager.cs +++ b/Project-Aurora/Project-Aurora/Settings/KeyboardLayoutManager.cs @@ -998,14 +998,14 @@ private void Configuration_PropertyChanged(object sender, System.ComponentModel. { if (e.PropertyName.Equals(nameof(Configuration.BitmapAccuracy))) { - Global.LightingStateManager.PostUpdate += this.LightingStateManager_PostUpdate; + Global.LightingStateManager.LightingStateManager.PostUpdate += this.LightingStateManager_PostUpdate; } } private void LightingStateManager_PostUpdate(object sender, EventArgs e) { this.LoadBrandDefault(); - Global.LightingStateManager.PostUpdate -= this.LightingStateManager_PostUpdate; + Global.LightingStateManager.LightingStateManager.PostUpdate -= this.LightingStateManager_PostUpdate; } public void CalculateBitmap() diff --git a/Project-Aurora/Project-Aurora/Settings/Overrides/Logic/Boolean/Boolean_ProcessRunning.cs b/Project-Aurora/Project-Aurora/Settings/Overrides/Logic/Boolean/Boolean_ProcessRunning.cs index c64a3471d..bb37bd8f1 100644 --- a/Project-Aurora/Project-Aurora/Settings/Overrides/Logic/Boolean/Boolean_ProcessRunning.cs +++ b/Project-Aurora/Project-Aurora/Settings/Overrides/Logic/Boolean/Boolean_ProcessRunning.cs @@ -1,5 +1,7 @@ using Aurora.Profiles; using Aurora.Utils; +using System.Diagnostics; +using System.IO; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; @@ -22,7 +24,7 @@ public BooleanProcessRunning() { } .WithBinding(TextBox.TextProperty, new Binding("ProcessName") { Source = this, Mode = BindingMode.TwoWay })); public bool Evaluate(IGameState gameState) - => Global.LightingStateManager.RunningProcessMonitor.IsProcessRunning(ProcessName); + => Process.GetProcessesByName(Path.GetFileNameWithoutExtension(ProcessName)).Length > 0; object IEvaluatable.Evaluate(IGameState gameState) => Evaluate(gameState); public void SetApplication(Application application) { }