diff --git a/src/Artemis.Core/Plugins/PluginFeature.cs b/src/Artemis.Core/Plugins/PluginFeature.cs index 149d42632..7d58d31cb 100644 --- a/src/Artemis.Core/Plugins/PluginFeature.cs +++ b/src/Artemis.Core/Plugins/PluginFeature.cs @@ -75,7 +75,8 @@ namespace Artemis.Core /// protected virtual void Dispose(bool disposing) { - if (disposing) InternalDisable(); + if (disposing) + SetEnabled(false); } /// @@ -104,16 +105,6 @@ namespace Artemis.Core Profiler.StopMeasurement("Update"); } - internal void StartRenderMeasure() - { - Profiler.StartMeasurement("Render"); - } - - internal void StopRenderMeasure() - { - Profiler.StopMeasurement("Render"); - } - internal void SetEnabled(bool enable, bool isAutoEnable = false) { if (enable == IsEnabled) diff --git a/src/Artemis.Core/Plugins/ScriptingProviders/Scripts/ProfileScript.cs b/src/Artemis.Core/Plugins/ScriptingProviders/Scripts/ProfileScript.cs index 5822e1884..8b5f18ce4 100644 --- a/src/Artemis.Core/Plugins/ScriptingProviders/Scripts/ProfileScript.cs +++ b/src/Artemis.Core/Plugins/ScriptingProviders/Scripts/ProfileScript.cs @@ -11,10 +11,6 @@ namespace Artemis.Core.ScriptingProviders protected ProfileScript(Profile profile, ScriptConfiguration configuration) : base(configuration) { Profile = profile; - lock (Profile.Scripts) - { - Profile.Scripts.Add(this); - } } /// diff --git a/src/Artemis.Core/Plugins/ScriptingProviders/Scripts/Script.cs b/src/Artemis.Core/Plugins/ScriptingProviders/Scripts/Script.cs index 1ddd8e5ac..279c18252 100644 --- a/src/Artemis.Core/Plugins/ScriptingProviders/Scripts/Script.cs +++ b/src/Artemis.Core/Plugins/ScriptingProviders/Scripts/Script.cs @@ -20,8 +20,6 @@ namespace Artemis.Core.ScriptingProviders throw new ArtemisCoreException("The provided script configuration already has an active script"); ScriptConfiguration = configuration; - ScriptConfiguration.Script = this; - ScriptConfiguration.PropertyChanged += ScriptConfigurationOnPropertyChanged; } diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index 9dee9fedb..8f9bfdbd5 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; +using System.Threading; using System.Threading.Tasks; using Artemis.Core.Ninject; using Artemis.Core.ScriptingProviders; @@ -58,7 +59,6 @@ namespace Artemis.Core.Services _frameStopWatch = new Stopwatch(); StartupArguments = new List(); - _rgbService.IsRenderPaused = true; _rgbService.Surface.Updating += SurfaceOnUpdating; _loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel(); } @@ -222,7 +222,7 @@ namespace Artemis.Core.Services _pluginManagementService.CopyBuiltInPlugins(); _pluginManagementService.LoadPlugins(StartupArguments, IsElevated); - _rgbService.IsRenderPaused = false; + _rgbService.SetRenderPaused(false); OnInitialized(); } diff --git a/src/Artemis.Core/Services/Input/InputService.cs b/src/Artemis.Core/Services/Input/InputService.cs index abb7ef643..9b42bc54f 100644 --- a/src/Artemis.Core/Services/Input/InputService.cs +++ b/src/Artemis.Core/Services/Input/InputService.cs @@ -305,10 +305,17 @@ namespace Artemis.Core.Services } } + public bool IsKeyDown(KeyboardKey key) + { + return _pressedKeys.Any(p => p.Value.Contains(key)); + } + #endregion #region Mouse + private readonly HashSet _pressedButtons = new(); + private void InputProviderOnMouseButtonDataReceived(object? sender, InputProviderMouseButtonEventArgs e) { bool foundLedId = InputKeyUtilities.MouseButtonLedIdMap.TryGetValue(e.Button, out LedId ledId); @@ -320,9 +327,17 @@ namespace Artemis.Core.Services ArtemisMouseButtonUpDownEventArgs eventArgs = new(e.Device, led, e.Button, e.IsDown); OnMouseButtonUpDown(eventArgs); if (e.IsDown) + { + if (!_pressedButtons.Contains(e.Button)) + _pressedButtons.Add(e.Button); OnMouseButtonDown(eventArgs); + } else + { + if (_pressedButtons.Contains(e.Button)) + _pressedButtons.Remove(e.Button); OnMouseButtonUp(eventArgs); + } // _logger.Verbose("Mouse button data: LED ID: {ledId}, button: {button}, is down: {isDown}, device: {device} ", ledId, e.Button, e.IsDown, e.Device); } @@ -339,6 +354,11 @@ namespace Artemis.Core.Services // _logger.Verbose("Mouse move data: XY: {X},{Y} - delta XY: {deltaX},{deltaY} - device: {device} ", e.CursorX, e.CursorY, e.DeltaX, e.DeltaY, e.Device); } + public bool IsButtonDown(MouseButton button) + { + return _pressedButtons.Contains(button); + } + #endregion #region Events diff --git a/src/Artemis.Core/Services/Input/Interfaces/IInputService.cs b/src/Artemis.Core/Services/Input/Interfaces/IInputService.cs index 3c2936354..19985f2de 100644 --- a/src/Artemis.Core/Services/Input/Interfaces/IInputService.cs +++ b/src/Artemis.Core/Services/Input/Interfaces/IInputService.cs @@ -40,7 +40,19 @@ namespace Artemis.Core.Services /// void ReleaseAll(); - #region Events + /// + /// Determines whether the provided key is pressed by any device + /// + /// The key to check + /// if the key is pressed; otherwise + bool IsKeyDown(KeyboardKey key); + + /// + /// Determines whether the button key is pressed by any device + /// + /// The button to check + /// if the button is pressed; otherwise + bool IsButtonDown(MouseButton button); /// /// Occurs whenever a key on a keyboard was pressed or released @@ -92,8 +104,6 @@ namespace Artemis.Core.Services /// public event EventHandler DeviceIdentified; - #endregion - #region Identification /// diff --git a/src/Artemis.Core/Services/Interfaces/IRgbService.cs b/src/Artemis.Core/Services/Interfaces/IRgbService.cs index 5420edb8f..c9bed101a 100644 --- a/src/Artemis.Core/Services/Interfaces/IRgbService.cs +++ b/src/Artemis.Core/Services/Interfaces/IRgbService.cs @@ -34,13 +34,13 @@ namespace Artemis.Core.Services /// /// Gets or sets whether rendering should be paused /// - bool IsRenderPaused { get; set; } + bool IsRenderPaused { get; } /// /// Gets a boolean indicating whether the render pipeline is open /// bool RenderOpen { get; } - + /// /// Gets or sets a boolean indicating whether to flush the RGB.NET LEDs during next update /// @@ -138,6 +138,13 @@ namespace Artemis.Core.Services /// The device to disable void DisableDevice(ArtemisDevice device); + /// + /// Pauses or resumes rendering, method won't return until the current frame finished rendering + /// + /// + /// if the pause state was changed; otherwise . + bool SetRenderPaused(bool paused); + /// /// Occurs when a single device was added /// diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs index 5e4841829..6c528bcfe 100644 --- a/src/Artemis.Core/Services/PluginManagementService.cs +++ b/src/Artemis.Core/Services/PluginManagementService.cs @@ -199,6 +199,12 @@ namespace Artemis.Core.Services public void LoadPlugins(List startupArguments, bool isElevated) { + if (startupArguments.Contains("--no-plugins")) + { + _logger.Warning("Artemis launched with --no-plugins, skipping the loading of plugins"); + return; + } + bool ignorePluginLock = startupArguments.Contains("--ignore-plugin-lock"); bool stayElevated = startupArguments.Contains("--force-elevation"); bool droppedAdmin = startupArguments.Contains("--dropped-admin"); diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs index da343b558..e814a0361 100644 --- a/src/Artemis.Core/Services/RgbService.cs +++ b/src/Artemis.Core/Services/RgbService.cs @@ -27,7 +27,6 @@ namespace Artemis.Core.Services private readonly PluginSetting _targetFrameRateSetting; private readonly TextureBrush _textureBrush = new(ITexture.Empty) {CalculationMode = RenderMode.Absolute}; private Dictionary _ledMap; - private bool _modifyingProviders; private ListLedGroup? _surfaceLedGroup; private SKTexture? _texture; @@ -51,6 +50,7 @@ namespace Artemis.Core.Services _ledMap = new Dictionary(); UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value}; + SetRenderPaused(true); Surface.RegisterUpdateTrigger(UpdateTrigger); Utilities.ShutdownRequested += UtilitiesOnShutdownRequested; @@ -71,7 +71,7 @@ namespace Artemis.Core.Services private void UtilitiesOnShutdownRequested(object? sender, EventArgs e) { - IsRenderPaused = true; + SetRenderPaused(true); } private void SurfaceOnLayoutChanged(SurfaceLayoutChangedEventArgs args) @@ -81,16 +81,14 @@ namespace Artemis.Core.Services private void UpdateLedGroup() { - lock (_devices) + bool changedRenderPaused = SetRenderPaused(true); + try { - if (_modifyingProviders) - return; - _ledMap = new Dictionary(_devices.SelectMany(d => d.Leds).ToDictionary(l => l.RgbLed)); if (_surfaceLedGroup == null) { - _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) {Brush = _textureBrush}; + _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) { Brush = _textureBrush }; OnLedsChanged(); return; } @@ -101,10 +99,16 @@ namespace Artemis.Core.Services _surfaceLedGroup.Detach(); // Apply the application wide brush and decorator - _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) {Brush = _textureBrush}; + _surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) { Brush = _textureBrush }; OnLedsChanged(); } } + finally + { + if (changedRenderPaused) + SetRenderPaused(false); + } + } private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e) @@ -141,95 +145,85 @@ namespace Artemis.Core.Services public void AddDeviceProvider(IRGBDeviceProvider deviceProvider) { - if (RenderOpen) - throw new ArtemisCoreException("Cannot add a device provider while rendering"); + bool changedRenderPaused = SetRenderPaused(true); - lock (_devices) + try { - try + List toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList(); + Surface.Detach(toRemove.Select(d => d.RgbDevice)); + foreach (ArtemisDevice device in toRemove) + RemoveDevice(device); + + List providerExceptions = new(); + + void DeviceProviderOnException(object? sender, ExceptionEventArgs e) { - _modifyingProviders = true; - - List toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList(); - Surface.Detach(toRemove.Select(d => d.RgbDevice)); - foreach (ArtemisDevice device in toRemove) - RemoveDevice(device); - - List providerExceptions = new(); - - void DeviceProviderOnException(object? sender, ExceptionEventArgs e) - { - if (e.IsCritical) - providerExceptions.Add(e.Exception); - else - _logger.Warning(e.Exception, "Device provider {deviceProvider} threw non-critical exception", deviceProvider.GetType().Name); - } - - deviceProvider.Exception += DeviceProviderOnException; - deviceProvider.Initialize(); - Surface.Attach(deviceProvider.Devices); - deviceProvider.Exception -= DeviceProviderOnException; - if (providerExceptions.Count == 1) - throw new ArtemisPluginException("RGB.NET threw exception: " + providerExceptions.First().Message, providerExceptions.First()); - if (providerExceptions.Count > 1) - throw new ArtemisPluginException("RGB.NET threw multiple exceptions", new AggregateException(providerExceptions)); - - if (!deviceProvider.Devices.Any()) - { - _logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name); - return; - } - - foreach (IRGBDevice rgbDevice in deviceProvider.Devices) - { - ArtemisDevice artemisDevice = GetArtemisDevice(rgbDevice); - AddDevice(artemisDevice); - _logger.Debug("Device provider {deviceProvider} added {deviceName}", deviceProvider.GetType().Name, rgbDevice.DeviceInfo.DeviceName); - } - - _devices.Sort((a, b) => a.ZIndex - b.ZIndex); + if (e.IsCritical) + providerExceptions.Add(e.Exception); + else + _logger.Warning(e.Exception, "Device provider {deviceProvider} threw non-critical exception", deviceProvider.GetType().Name); } - catch (Exception e) + + deviceProvider.Exception += DeviceProviderOnException; + deviceProvider.Initialize(); + Surface.Attach(deviceProvider.Devices); + deviceProvider.Exception -= DeviceProviderOnException; + if (providerExceptions.Count == 1) + throw new ArtemisPluginException("RGB.NET threw exception: " + providerExceptions.First().Message, providerExceptions.First()); + if (providerExceptions.Count > 1) + throw new ArtemisPluginException("RGB.NET threw multiple exceptions", new AggregateException(providerExceptions)); + + if (!deviceProvider.Devices.Any()) { - _logger.Error(e, "Exception during device loading for device provider {deviceProvider}", deviceProvider.GetType().Name); - throw; + _logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name); + return; } - finally + + foreach (IRGBDevice rgbDevice in deviceProvider.Devices) { - _modifyingProviders = false; - UpdateLedGroup(); + ArtemisDevice artemisDevice = GetArtemisDevice(rgbDevice); + AddDevice(artemisDevice); + _logger.Debug("Device provider {deviceProvider} added {deviceName}", deviceProvider.GetType().Name, rgbDevice.DeviceInfo.DeviceName); } + + _devices.Sort((a, b) => a.ZIndex - b.ZIndex); + } + catch (Exception e) + { + _logger.Error(e, "Exception during device loading for device provider {deviceProvider}", deviceProvider.GetType().Name); + throw; + } + finally + { + UpdateLedGroup(); + if (changedRenderPaused) + SetRenderPaused(false); } } public void RemoveDeviceProvider(IRGBDeviceProvider deviceProvider) { - if (RenderOpen) - throw new ArtemisCoreException("Cannot update the remove device provider while rendering"); + bool changedRenderPaused = SetRenderPaused(true); - lock (_devices) + try { - try - { - _modifyingProviders = true; + List toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList(); + Surface.Detach(toRemove.Select(d => d.RgbDevice)); + foreach (ArtemisDevice device in toRemove) + RemoveDevice(device); - List toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList(); - Surface.Detach(toRemove.Select(d => d.RgbDevice)); - foreach (ArtemisDevice device in toRemove) - RemoveDevice(device); - - _devices.Sort((a, b) => a.ZIndex - b.ZIndex); - } - catch (Exception e) - { - _logger.Error(e, "Exception during device removal for device provider {deviceProvider}", deviceProvider.GetType().Name); - throw; - } - finally - { - _modifyingProviders = false; - UpdateLedGroup(); - } + _devices.Sort((a, b) => a.ZIndex - b.ZIndex); + } + catch (Exception e) + { + _logger.Error(e, "Exception during device removal for device provider {deviceProvider}", deviceProvider.GetType().Name); + throw; + } + finally + { + UpdateLedGroup(); + if (changedRenderPaused) + SetRenderPaused(false); } } @@ -241,6 +235,24 @@ namespace Artemis.Core.Services Surface.Dispose(); } + public bool SetRenderPaused(bool paused) + { + if (IsRenderPaused == paused) + return false; + + if (paused) + { + UpdateTrigger.Stop(); + } + else + { + UpdateTrigger.Start(); + } + + IsRenderPaused = paused; + return true; + } + public event EventHandler? DeviceAdded; public event EventHandler? DeviceRemoved; public event EventHandler? LedsChanged; @@ -326,12 +338,22 @@ namespace Artemis.Core.Services public void AutoArrangeDevices() { - SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement(); - surfaceArrangement.Arrange(_devices); - foreach (ArtemisDevice artemisDevice in _devices) - artemisDevice.ApplyDefaultCategories(); + bool changedRenderPaused = SetRenderPaused(true); - SaveDevices(); + try + { + SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement(); + surfaceArrangement.Arrange(_devices); + foreach (ArtemisDevice artemisDevice in _devices) + artemisDevice.ApplyDefaultCategories(); + + SaveDevices(); + } + finally + { + if (changedRenderPaused) + SetRenderPaused(false); + } } public ArtemisLayout? ApplyBestDeviceLayout(ArtemisDevice device) @@ -402,7 +424,7 @@ namespace Artemis.Core.Services _deviceRepository.Save(device.DeviceEntity); DeviceProvider deviceProvider = device.DeviceProvider; - + // Feels bad but need to in order to get the initial LEDs back _pluginManagementService.DisablePluginFeature(deviceProvider, false); Thread.Sleep(500); diff --git a/src/Artemis.Core/Services/ScriptingService.cs b/src/Artemis.Core/Services/ScriptingService.cs index 38db76e16..36b030d1f 100644 --- a/src/Artemis.Core/Services/ScriptingService.cs +++ b/src/Artemis.Core/Services/ScriptingService.cs @@ -6,17 +6,20 @@ using System.Reflection; using Artemis.Core.ScriptingProviders; using Ninject; using Ninject.Parameters; +using Serilog; namespace Artemis.Core.Services { internal class ScriptingService : IScriptingService { + private readonly ILogger _logger; private readonly IPluginManagementService _pluginManagementService; private readonly IProfileService _profileService; private List _scriptingProviders; - public ScriptingService(IPluginManagementService pluginManagementService, IProfileService profileService) + public ScriptingService(ILogger logger, IPluginManagementService pluginManagementService, IProfileService profileService) { + _logger = logger; _pluginManagementService = pluginManagementService; _profileService = profileService; @@ -81,43 +84,71 @@ namespace Artemis.Core.Services public GlobalScript? CreateScriptInstance(ScriptConfiguration scriptConfiguration) { - if (scriptConfiguration.Script != null) - throw new ArtemisCoreException("The provided script configuration already has an active script"); + GlobalScript? script = null; + try + { + if (scriptConfiguration.Script != null) + throw new ArtemisCoreException("The provided script configuration already has an active script"); - ScriptingProvider? provider = _scriptingProviders.FirstOrDefault(p => p.Id == scriptConfiguration.ScriptingProviderId); - if (provider == null) + ScriptingProvider? provider = _scriptingProviders.FirstOrDefault(p => p.Id == scriptConfiguration.ScriptingProviderId); + if (provider == null) + return null; + + script = (GlobalScript) provider.Plugin.Kernel!.Get( + provider.GlobalScriptType, + CreateScriptConstructorArgument(provider.GlobalScriptType, scriptConfiguration) + ); + + script.ScriptingProvider = provider; + script.ScriptingService = this; + provider.InternalScripts.Add(script); + InternalGlobalScripts.Add(script); + + scriptConfiguration.Script = script; + return script; + } + catch (Exception e) + { + _logger.Warning(e, "Failed to initialize global script"); + script?.Dispose(); return null; - - GlobalScript script = (GlobalScript) provider.Plugin.Kernel!.Get( - provider.GlobalScriptType, - CreateScriptConstructorArgument(provider.GlobalScriptType, scriptConfiguration) - ); - - script.ScriptingProvider = provider; - script.ScriptingService = this; - provider.InternalScripts.Add(script); - InternalGlobalScripts.Add(script); - return script; + } } public ProfileScript? CreateScriptInstance(Profile profile, ScriptConfiguration scriptConfiguration) { - if (scriptConfiguration.Script != null) - throw new ArtemisCoreException("The provided script configuration already has an active script"); + ProfileScript? script = null; + try + { + if (scriptConfiguration.Script != null) + throw new ArtemisCoreException("The provided script configuration already has an active script"); - ScriptingProvider? provider = _scriptingProviders.FirstOrDefault(p => p.Id == scriptConfiguration.ScriptingProviderId); - if (provider == null) + ScriptingProvider? provider = _scriptingProviders.FirstOrDefault(p => p.Id == scriptConfiguration.ScriptingProviderId); + if (provider == null) + return null; + + script = (ProfileScript) provider.Plugin.Kernel!.Get( + provider.ProfileScriptType, + CreateScriptConstructorArgument(provider.ProfileScriptType, profile), + CreateScriptConstructorArgument(provider.ProfileScriptType, scriptConfiguration) + ); + + script.ScriptingProvider = provider; + provider.InternalScripts.Add(script); + lock (profile) + { + scriptConfiguration.Script = script; + profile.Scripts.Add(script); + } + + return script; + } + catch (Exception e) + { + _logger.Warning(e, "Failed to initialize profile script"); + script?.Dispose(); return null; - - ProfileScript script = (ProfileScript) provider.Plugin.Kernel!.Get( - provider.ProfileScriptType, - CreateScriptConstructorArgument(provider.ProfileScriptType, profile), - CreateScriptConstructorArgument(provider.ProfileScriptType, scriptConfiguration) - ); - - script.ScriptingProvider = provider; - provider.InternalScripts.Add(script); - return script; + } } /// diff --git a/src/Artemis.UI/ApplicationStateManager.cs b/src/Artemis.UI/ApplicationStateManager.cs index 45dc2098c..d2ac6eb02 100644 --- a/src/Artemis.UI/ApplicationStateManager.cs +++ b/src/Artemis.UI/ApplicationStateManager.cs @@ -92,7 +92,10 @@ namespace Artemis.UI using HttpClient client = new(); try { - HttpResponseMessage httpResponseMessage = client.Send(new HttpRequestMessage(HttpMethod.Post, url + "remote/bring-to-foreground")); + CancellationTokenSource cts = new(); + cts.CancelAfter(2000); + + HttpResponseMessage httpResponseMessage = client.Send(new HttpRequestMessage(HttpMethod.Post, url + "remote/bring-to-foreground"), cts.Token); httpResponseMessage.EnsureSuccessStatusCode(); return true; } diff --git a/src/Artemis.UI/Providers/NativeWindowInputProvider.cs b/src/Artemis.UI/Providers/NativeWindowInputProvider.cs index a6aa38e96..25e8f0471 100644 --- a/src/Artemis.UI/Providers/NativeWindowInputProvider.cs +++ b/src/Artemis.UI/Providers/NativeWindowInputProvider.cs @@ -21,6 +21,7 @@ namespace Artemis.UI.Providers private readonly IInputService _inputService; private readonly ILogger _logger; private DateTime _lastMouseUpdate; + private int _lastProcessId; private SpongeWindow _sponge; private System.Timers.Timer _taskManagerTimer; @@ -88,9 +89,15 @@ namespace Artemis.UI.Providers private void TaskManagerTimerOnElapsed(object sender, ElapsedEventArgs e) { + int processId = WindowUtilities.GetActiveProcessId(); + if (processId == _lastProcessId) + return; + + _lastProcessId = processId; + // If task manager has focus then we can't track keys properly, release everything to avoid them getting stuck // Same goes for Idle which is what you get when you press Ctrl+Alt+Del - Process active = Process.GetProcessById(WindowUtilities.GetActiveProcessId()); + Process active = Process.GetProcessById(processId); if (active?.ProcessName == "Taskmgr" || active?.ProcessName == "Idle") _inputService.ReleaseAll(); } @@ -164,7 +171,7 @@ namespace Artemis.UI.Providers private int _mouseDeltaX; private int _mouseDeltaY; - + private void HandleMouseData(RawInputData data, RawInputMouseData mouseData) { // Only submit mouse movement 25 times per second but increment the delta diff --git a/src/Artemis.UI/Screens/Home/HomeView.xaml b/src/Artemis.UI/Screens/Home/HomeView.xaml index ce8cd134b..1f6d99cc9 100644 --- a/src/Artemis.UI/Screens/Home/HomeView.xaml +++ b/src/Artemis.UI/Screens/Home/HomeView.xaml @@ -38,199 +38,185 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - + + - - + + - + - Have a chat - Plugins + - If you need help, have some feedback or have any other questions feel free to contact us through any of the - following channels. + Artemis is built up using plugins. This means devices, brushes, effects and modules (for supporting games!) can all be added via plugins. + Under Settings > Plugins you can find your currently installed plugins, these default plugins are created by Artemis developers. + + We're also keeping track of a list of third-party plugins on our wiki. - - - - - - - - - - - - - + + - - - - - - - - - - - - - Open Source - - This project is completely open source. If you like it and want to say thanks you could hit the GitHub Star button, - I like numbers. You could even make plugins, there's a full documentation on the website - - - - - - - Feel like you want to make a donation? It would be gratefully received. Click the button to donate via PayPal. + + + + + + + + + + + + + + Have a chat + + If you need help, have some feedback or have any other questions feel free to contact us through any of the + following channels. - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Open Source + + This project is completely open source. If you like it and want to say thanks you could hit the GitHub Star button, + I like numbers. You could even make plugins, there's a full documentation on the website + + + + + + + Feel like you want to make a donation? It would be gratefully received. Click the button to donate via PayPal. + + + + + + - - - \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/Dialogs/TimelineSegmentDialogViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/Dialogs/TimelineSegmentDialogViewModel.cs index 4267951b9..8f2b0585a 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/Dialogs/TimelineSegmentDialogViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/Dialogs/TimelineSegmentDialogViewModel.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.Text.RegularExpressions; using System.Threading.Tasks; using Artemis.UI.Shared.Services; -using Castle.Core.Internal; using FluentValidation; using Stylet; @@ -70,7 +69,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline.Dialogs if (parts.Length == 1) return TimeSpan.FromSeconds(double.Parse(parts[0])); // Only milliseconds provided with a leading . - if (parts[0].IsNullOrEmpty()) + if (string.IsNullOrEmpty(parts[0])) { // Add trailing zeros so 2.5 becomes 2.500, can't seem to make double.Parse do that while (parts[0].Length < 3) parts[0] += "0"; diff --git a/src/Artemis.UI/Screens/RootView.xaml b/src/Artemis.UI/Screens/RootView.xaml index 50eebd295..4ad50b41c 100644 --- a/src/Artemis.UI/Screens/RootView.xaml +++ b/src/Artemis.UI/Screens/RootView.xaml @@ -61,6 +61,19 @@ VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" /> + + + + + + + + + Activating profile... + + + + - Robert 'Spoinky' Beekman + Robert Beekman + CommandParameter="https://github.com/RobertWasTaken/"> diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsTabView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsTabView.xaml index e0f0eba86..bbd48ac62 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsTabView.xaml +++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsTabView.xaml @@ -20,6 +20,7 @@ + The list below shows all loaded plugins. @@ -38,7 +39,17 @@ Margin="5 0" Text="{Binding SearchPluginInput, Delay=300, UpdateSourceTrigger=PropertyChanged}" /> - + +