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

Merge branch 'development'

This commit is contained in:
Robert 2021-09-03 22:17:44 +02:00
commit 5fa549be61
24 changed files with 1804 additions and 336 deletions

View File

@ -75,7 +75,8 @@ namespace Artemis.Core
/// </param> /// </param>
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (disposing) InternalDisable(); if (disposing)
SetEnabled(false);
} }
/// <summary> /// <summary>
@ -104,16 +105,6 @@ namespace Artemis.Core
Profiler.StopMeasurement("Update"); Profiler.StopMeasurement("Update");
} }
internal void StartRenderMeasure()
{
Profiler.StartMeasurement("Render");
}
internal void StopRenderMeasure()
{
Profiler.StopMeasurement("Render");
}
internal void SetEnabled(bool enable, bool isAutoEnable = false) internal void SetEnabled(bool enable, bool isAutoEnable = false)
{ {
if (enable == IsEnabled) if (enable == IsEnabled)

View File

@ -11,10 +11,6 @@ namespace Artemis.Core.ScriptingProviders
protected ProfileScript(Profile profile, ScriptConfiguration configuration) : base(configuration) protected ProfileScript(Profile profile, ScriptConfiguration configuration) : base(configuration)
{ {
Profile = profile; Profile = profile;
lock (Profile.Scripts)
{
Profile.Scripts.Add(this);
}
} }
/// <summary> /// <summary>

View File

@ -20,8 +20,6 @@ namespace Artemis.Core.ScriptingProviders
throw new ArtemisCoreException("The provided script configuration already has an active script"); throw new ArtemisCoreException("The provided script configuration already has an active script");
ScriptConfiguration = configuration; ScriptConfiguration = configuration;
ScriptConfiguration.Script = this;
ScriptConfiguration.PropertyChanged += ScriptConfigurationOnPropertyChanged; ScriptConfiguration.PropertyChanged += ScriptConfigurationOnPropertyChanged;
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core.Ninject; using Artemis.Core.Ninject;
using Artemis.Core.ScriptingProviders; using Artemis.Core.ScriptingProviders;
@ -58,7 +59,6 @@ namespace Artemis.Core.Services
_frameStopWatch = new Stopwatch(); _frameStopWatch = new Stopwatch();
StartupArguments = new List<string>(); StartupArguments = new List<string>();
_rgbService.IsRenderPaused = true;
_rgbService.Surface.Updating += SurfaceOnUpdating; _rgbService.Surface.Updating += SurfaceOnUpdating;
_loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel(); _loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel();
} }
@ -222,7 +222,7 @@ namespace Artemis.Core.Services
_pluginManagementService.CopyBuiltInPlugins(); _pluginManagementService.CopyBuiltInPlugins();
_pluginManagementService.LoadPlugins(StartupArguments, IsElevated); _pluginManagementService.LoadPlugins(StartupArguments, IsElevated);
_rgbService.IsRenderPaused = false; _rgbService.SetRenderPaused(false);
OnInitialized(); OnInitialized();
} }

View File

@ -305,10 +305,17 @@ namespace Artemis.Core.Services
} }
} }
public bool IsKeyDown(KeyboardKey key)
{
return _pressedKeys.Any(p => p.Value.Contains(key));
}
#endregion #endregion
#region Mouse #region Mouse
private readonly HashSet<MouseButton> _pressedButtons = new();
private void InputProviderOnMouseButtonDataReceived(object? sender, InputProviderMouseButtonEventArgs e) private void InputProviderOnMouseButtonDataReceived(object? sender, InputProviderMouseButtonEventArgs e)
{ {
bool foundLedId = InputKeyUtilities.MouseButtonLedIdMap.TryGetValue(e.Button, out LedId ledId); 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); ArtemisMouseButtonUpDownEventArgs eventArgs = new(e.Device, led, e.Button, e.IsDown);
OnMouseButtonUpDown(eventArgs); OnMouseButtonUpDown(eventArgs);
if (e.IsDown) if (e.IsDown)
{
if (!_pressedButtons.Contains(e.Button))
_pressedButtons.Add(e.Button);
OnMouseButtonDown(eventArgs); OnMouseButtonDown(eventArgs);
}
else else
{
if (_pressedButtons.Contains(e.Button))
_pressedButtons.Remove(e.Button);
OnMouseButtonUp(eventArgs); OnMouseButtonUp(eventArgs);
}
// _logger.Verbose("Mouse button data: LED ID: {ledId}, button: {button}, is down: {isDown}, device: {device} ", ledId, e.Button, e.IsDown, e.Device); // _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); // _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 #endregion
#region Events #region Events

View File

@ -40,7 +40,19 @@ namespace Artemis.Core.Services
/// </summary> /// </summary>
void ReleaseAll(); void ReleaseAll();
#region Events /// <summary>
/// Determines whether the provided key is pressed by any device
/// </summary>
/// <param name="key">The key to check</param>
/// <returns><see langword="true" /> if the key is pressed; otherwise <see langword="false" /></returns>
bool IsKeyDown(KeyboardKey key);
/// <summary>
/// Determines whether the button key is pressed by any device
/// </summary>
/// <param name="button">The button to check</param>
/// <returns><see langword="true" /> if the button is pressed; otherwise <see langword="false" /></returns>
bool IsButtonDown(MouseButton button);
/// <summary> /// <summary>
/// Occurs whenever a key on a keyboard was pressed or released /// Occurs whenever a key on a keyboard was pressed or released
@ -92,8 +104,6 @@ namespace Artemis.Core.Services
/// </summary> /// </summary>
public event EventHandler DeviceIdentified; public event EventHandler DeviceIdentified;
#endregion
#region Identification #region Identification
/// <summary> /// <summary>

View File

@ -34,7 +34,7 @@ namespace Artemis.Core.Services
/// <summary> /// <summary>
/// Gets or sets whether rendering should be paused /// Gets or sets whether rendering should be paused
/// </summary> /// </summary>
bool IsRenderPaused { get; set; } bool IsRenderPaused { get; }
/// <summary> /// <summary>
/// Gets a boolean indicating whether the render pipeline is open /// Gets a boolean indicating whether the render pipeline is open
@ -138,6 +138,13 @@ namespace Artemis.Core.Services
/// <param name="device">The device to disable</param> /// <param name="device">The device to disable</param>
void DisableDevice(ArtemisDevice device); void DisableDevice(ArtemisDevice device);
/// <summary>
/// Pauses or resumes rendering, method won't return until the current frame finished rendering
/// </summary>
/// <param name="paused"></param>
/// <returns><see langword="true"/> if the pause state was changed; otherwise <see langword="false"/>.</returns>
bool SetRenderPaused(bool paused);
/// <summary> /// <summary>
/// Occurs when a single device was added /// Occurs when a single device was added
/// </summary> /// </summary>

View File

@ -199,6 +199,12 @@ namespace Artemis.Core.Services
public void LoadPlugins(List<string> startupArguments, bool isElevated) public void LoadPlugins(List<string> 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 ignorePluginLock = startupArguments.Contains("--ignore-plugin-lock");
bool stayElevated = startupArguments.Contains("--force-elevation"); bool stayElevated = startupArguments.Contains("--force-elevation");
bool droppedAdmin = startupArguments.Contains("--dropped-admin"); bool droppedAdmin = startupArguments.Contains("--dropped-admin");

View File

@ -27,7 +27,6 @@ namespace Artemis.Core.Services
private readonly PluginSetting<int> _targetFrameRateSetting; private readonly PluginSetting<int> _targetFrameRateSetting;
private readonly TextureBrush _textureBrush = new(ITexture.Empty) {CalculationMode = RenderMode.Absolute}; private readonly TextureBrush _textureBrush = new(ITexture.Empty) {CalculationMode = RenderMode.Absolute};
private Dictionary<Led, ArtemisLed> _ledMap; private Dictionary<Led, ArtemisLed> _ledMap;
private bool _modifyingProviders;
private ListLedGroup? _surfaceLedGroup; private ListLedGroup? _surfaceLedGroup;
private SKTexture? _texture; private SKTexture? _texture;
@ -51,6 +50,7 @@ namespace Artemis.Core.Services
_ledMap = new Dictionary<Led, ArtemisLed>(); _ledMap = new Dictionary<Led, ArtemisLed>();
UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value}; UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value};
SetRenderPaused(true);
Surface.RegisterUpdateTrigger(UpdateTrigger); Surface.RegisterUpdateTrigger(UpdateTrigger);
Utilities.ShutdownRequested += UtilitiesOnShutdownRequested; Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
@ -71,7 +71,7 @@ namespace Artemis.Core.Services
private void UtilitiesOnShutdownRequested(object? sender, EventArgs e) private void UtilitiesOnShutdownRequested(object? sender, EventArgs e)
{ {
IsRenderPaused = true; SetRenderPaused(true);
} }
private void SurfaceOnLayoutChanged(SurfaceLayoutChangedEventArgs args) private void SurfaceOnLayoutChanged(SurfaceLayoutChangedEventArgs args)
@ -81,11 +81,9 @@ namespace Artemis.Core.Services
private void UpdateLedGroup() private void UpdateLedGroup()
{ {
lock (_devices) bool changedRenderPaused = SetRenderPaused(true);
try
{ {
if (_modifyingProviders)
return;
_ledMap = new Dictionary<Led, ArtemisLed>(_devices.SelectMany(d => d.Leds).ToDictionary(l => l.RgbLed)); _ledMap = new Dictionary<Led, ArtemisLed>(_devices.SelectMany(d => d.Leds).ToDictionary(l => l.RgbLed));
if (_surfaceLedGroup == null) if (_surfaceLedGroup == null)
@ -105,6 +103,12 @@ namespace Artemis.Core.Services
OnLedsChanged(); OnLedsChanged();
} }
} }
finally
{
if (changedRenderPaused)
SetRenderPaused(false);
}
} }
private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e) private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e)
@ -141,15 +145,10 @@ namespace Artemis.Core.Services
public void AddDeviceProvider(IRGBDeviceProvider deviceProvider) public void AddDeviceProvider(IRGBDeviceProvider deviceProvider)
{ {
if (RenderOpen) bool changedRenderPaused = SetRenderPaused(true);
throw new ArtemisCoreException("Cannot add a device provider while rendering");
lock (_devices)
{
try try
{ {
_modifyingProviders = true;
List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList(); List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
Surface.Detach(toRemove.Select(d => d.RgbDevice)); Surface.Detach(toRemove.Select(d => d.RgbDevice));
foreach (ArtemisDevice device in toRemove) foreach (ArtemisDevice device in toRemove)
@ -196,23 +195,18 @@ namespace Artemis.Core.Services
} }
finally finally
{ {
_modifyingProviders = false;
UpdateLedGroup(); UpdateLedGroup();
} if (changedRenderPaused)
SetRenderPaused(false);
} }
} }
public void RemoveDeviceProvider(IRGBDeviceProvider deviceProvider) public void RemoveDeviceProvider(IRGBDeviceProvider deviceProvider)
{ {
if (RenderOpen) bool changedRenderPaused = SetRenderPaused(true);
throw new ArtemisCoreException("Cannot update the remove device provider while rendering");
lock (_devices)
{
try try
{ {
_modifyingProviders = true;
List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList(); List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
Surface.Detach(toRemove.Select(d => d.RgbDevice)); Surface.Detach(toRemove.Select(d => d.RgbDevice));
foreach (ArtemisDevice device in toRemove) foreach (ArtemisDevice device in toRemove)
@ -227,9 +221,9 @@ namespace Artemis.Core.Services
} }
finally finally
{ {
_modifyingProviders = false;
UpdateLedGroup(); UpdateLedGroup();
} if (changedRenderPaused)
SetRenderPaused(false);
} }
} }
@ -241,6 +235,24 @@ namespace Artemis.Core.Services
Surface.Dispose(); 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<DeviceEventArgs>? DeviceAdded; public event EventHandler<DeviceEventArgs>? DeviceAdded;
public event EventHandler<DeviceEventArgs>? DeviceRemoved; public event EventHandler<DeviceEventArgs>? DeviceRemoved;
public event EventHandler? LedsChanged; public event EventHandler? LedsChanged;
@ -325,6 +337,10 @@ namespace Artemis.Core.Services
#region EnabledDevices #region EnabledDevices
public void AutoArrangeDevices() public void AutoArrangeDevices()
{
bool changedRenderPaused = SetRenderPaused(true);
try
{ {
SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement(); SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement();
surfaceArrangement.Arrange(_devices); surfaceArrangement.Arrange(_devices);
@ -333,6 +349,12 @@ namespace Artemis.Core.Services
SaveDevices(); SaveDevices();
} }
finally
{
if (changedRenderPaused)
SetRenderPaused(false);
}
}
public ArtemisLayout? ApplyBestDeviceLayout(ArtemisDevice device) public ArtemisLayout? ApplyBestDeviceLayout(ArtemisDevice device)
{ {

View File

@ -6,17 +6,20 @@ using System.Reflection;
using Artemis.Core.ScriptingProviders; using Artemis.Core.ScriptingProviders;
using Ninject; using Ninject;
using Ninject.Parameters; using Ninject.Parameters;
using Serilog;
namespace Artemis.Core.Services namespace Artemis.Core.Services
{ {
internal class ScriptingService : IScriptingService internal class ScriptingService : IScriptingService
{ {
private readonly ILogger _logger;
private readonly IPluginManagementService _pluginManagementService; private readonly IPluginManagementService _pluginManagementService;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private List<ScriptingProvider> _scriptingProviders; private List<ScriptingProvider> _scriptingProviders;
public ScriptingService(IPluginManagementService pluginManagementService, IProfileService profileService) public ScriptingService(ILogger logger, IPluginManagementService pluginManagementService, IProfileService profileService)
{ {
_logger = logger;
_pluginManagementService = pluginManagementService; _pluginManagementService = pluginManagementService;
_profileService = profileService; _profileService = profileService;
@ -80,6 +83,9 @@ namespace Artemis.Core.Services
public ReadOnlyCollection<GlobalScript> GlobalScripts => InternalGlobalScripts.AsReadOnly(); public ReadOnlyCollection<GlobalScript> GlobalScripts => InternalGlobalScripts.AsReadOnly();
public GlobalScript? CreateScriptInstance(ScriptConfiguration scriptConfiguration) public GlobalScript? CreateScriptInstance(ScriptConfiguration scriptConfiguration)
{
GlobalScript? script = null;
try
{ {
if (scriptConfiguration.Script != null) if (scriptConfiguration.Script != null)
throw new ArtemisCoreException("The provided script configuration already has an active script"); throw new ArtemisCoreException("The provided script configuration already has an active script");
@ -88,7 +94,7 @@ namespace Artemis.Core.Services
if (provider == null) if (provider == null)
return null; return null;
GlobalScript script = (GlobalScript) provider.Plugin.Kernel!.Get( script = (GlobalScript) provider.Plugin.Kernel!.Get(
provider.GlobalScriptType, provider.GlobalScriptType,
CreateScriptConstructorArgument(provider.GlobalScriptType, scriptConfiguration) CreateScriptConstructorArgument(provider.GlobalScriptType, scriptConfiguration)
); );
@ -97,10 +103,22 @@ namespace Artemis.Core.Services
script.ScriptingService = this; script.ScriptingService = this;
provider.InternalScripts.Add(script); provider.InternalScripts.Add(script);
InternalGlobalScripts.Add(script); InternalGlobalScripts.Add(script);
scriptConfiguration.Script = script;
return script; return script;
} }
catch (Exception e)
{
_logger.Warning(e, "Failed to initialize global script");
script?.Dispose();
return null;
}
}
public ProfileScript? CreateScriptInstance(Profile profile, ScriptConfiguration scriptConfiguration) public ProfileScript? CreateScriptInstance(Profile profile, ScriptConfiguration scriptConfiguration)
{
ProfileScript? script = null;
try
{ {
if (scriptConfiguration.Script != null) if (scriptConfiguration.Script != null)
throw new ArtemisCoreException("The provided script configuration already has an active script"); throw new ArtemisCoreException("The provided script configuration already has an active script");
@ -109,7 +127,7 @@ namespace Artemis.Core.Services
if (provider == null) if (provider == null)
return null; return null;
ProfileScript script = (ProfileScript) provider.Plugin.Kernel!.Get( script = (ProfileScript) provider.Plugin.Kernel!.Get(
provider.ProfileScriptType, provider.ProfileScriptType,
CreateScriptConstructorArgument(provider.ProfileScriptType, profile), CreateScriptConstructorArgument(provider.ProfileScriptType, profile),
CreateScriptConstructorArgument(provider.ProfileScriptType, scriptConfiguration) CreateScriptConstructorArgument(provider.ProfileScriptType, scriptConfiguration)
@ -117,8 +135,21 @@ namespace Artemis.Core.Services
script.ScriptingProvider = provider; script.ScriptingProvider = provider;
provider.InternalScripts.Add(script); provider.InternalScripts.Add(script);
lock (profile)
{
scriptConfiguration.Script = script;
profile.Scripts.Add(script);
}
return script; return script;
} }
catch (Exception e)
{
_logger.Warning(e, "Failed to initialize profile script");
script?.Dispose();
return null;
}
}
/// <inheritdoc /> /// <inheritdoc />
public void DeleteScript(ScriptConfiguration scriptConfiguration) public void DeleteScript(ScriptConfiguration scriptConfiguration)

View File

@ -92,7 +92,10 @@ namespace Artemis.UI
using HttpClient client = new(); using HttpClient client = new();
try 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(); httpResponseMessage.EnsureSuccessStatusCode();
return true; return true;
} }

View File

@ -21,6 +21,7 @@ namespace Artemis.UI.Providers
private readonly IInputService _inputService; private readonly IInputService _inputService;
private readonly ILogger _logger; private readonly ILogger _logger;
private DateTime _lastMouseUpdate; private DateTime _lastMouseUpdate;
private int _lastProcessId;
private SpongeWindow _sponge; private SpongeWindow _sponge;
private System.Timers.Timer _taskManagerTimer; private System.Timers.Timer _taskManagerTimer;
@ -88,9 +89,15 @@ namespace Artemis.UI.Providers
private void TaskManagerTimerOnElapsed(object sender, ElapsedEventArgs e) 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 // 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 // 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") if (active?.ProcessName == "Taskmgr" || active?.ProcessName == "Idle")
_inputService.ReleaseAll(); _inputService.ReleaseAll();
} }

View File

@ -38,9 +38,8 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image Source="{svgc:SvgImage Source=/Resources/Images/Logo/bow.svg}" Height="100" Width="100" /> <Image Source="{svgc:SvgImage Source=/Resources/Images/Logo/bow.svg}" Height="80" Width="80" />
<StackPanel Grid.Column="1" Margin="24 0 0 0" VerticalAlignment="Center"> <TextBlock Grid.Column="1" Margin="24 0 0 0" VerticalAlignment="Center" Style="{StaticResource MaterialDesignHeadline4TextBlock}" TextWrapping="Wrap">
<TextBlock Style="{StaticResource MaterialDesignHeadline4TextBlock}" TextWrapping="Wrap">
<Run Text="Welcome to Artemis, the unified" /> <Run Text="Welcome to Artemis, the unified" />
<Run Text="RGB"> <Run Text="RGB">
<Run.Foreground> <Run.Foreground>
@ -56,27 +55,54 @@
</Run> </Run>
<Run Text="platform." /> <Run Text="platform." />
</TextBlock> </TextBlock>
<Button Style="{StaticResource MaterialDesignFlatButton}"
Foreground="{StaticResource SecondaryHueMidBrush}"
materialDesign:RippleAssist.Feedback="{StaticResource SecondaryHueMidBrush}"
Command="{x:Static materialDesign:DrawerHost.OpenDrawerCommand}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Binoculars" />
<TextBlock Margin="8 0 0 0">EXPLORE</TextBlock>
</StackPanel>
</Button>
</StackPanel>
</Grid> </Grid>
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" <ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Bottom" VerticalAlignment="Bottom"
Margin="0 0 0 32"> Margin="0 0 0 32">
<StackPanel>
<materialDesign:Card Width="852" Margin="8" Height="Auto">
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<materialDesign:PackIcon Kind="Plug" Width="140" Height="140" HorizontalAlignment="Center" VerticalAlignment="Center" />
<StackPanel Grid.Row="0" Grid.Column="1">
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Plugins</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
TextWrapping="Wrap" Margin="16 0 16 8"
Foreground="{DynamicResource MaterialDesignBodyLight}"
VerticalAlignment="Top">
Artemis is built up using plugins. This means devices, brushes, effects and modules (for supporting games!) can all be added via plugins. <LineBreak /> <LineBreak />
Under Settings > Plugins you can find your currently installed plugins, these default plugins are created by Artemis developers.
<LineBreak /> <LineBreak />
We're also keeping track of a list of third-party plugins on our wiki.
</TextBlock>
</StackPanel>
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0" BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
<Button Style="{DynamicResource MaterialDesignFlatButton}"
HorizontalAlignment="Right"
Command="{s:Action OpenUrl}"
CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/plugins">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="OpenInBrowser" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Get more plugins</TextBlock>
</StackPanel>
</Button>
</Border>
</Grid>
</materialDesign:Card>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto"> <materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
<Grid VerticalAlignment="Stretch"> <Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="155" /> <RowDefinition Height="175" />
<RowDefinition Height="95" /> <RowDefinition Height="95" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -87,7 +113,8 @@
HorizontalAlignment="Center" VerticalAlignment="Center" /> HorizontalAlignment="Center" VerticalAlignment="Center" />
<StackPanel Grid.Row="0" Grid.Column="1"> <StackPanel Grid.Row="0" Grid.Column="1">
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Have a chat</TextBlock> <TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Have a chat</TextBlock>
<TextBlock TextWrapping="Wrap" Margin="16 0 16 8" <TextBlock Style="{StaticResource MaterialDesignTextBlock}"
TextWrapping="Wrap" Margin="16 0 16 8"
Foreground="{DynamicResource MaterialDesignBodyLight}" Foreground="{DynamicResource MaterialDesignBodyLight}"
VerticalAlignment="Top"> VerticalAlignment="Top">
If you need help, have some feedback or have any other questions feel free to contact us through any of the If you need help, have some feedback or have any other questions feel free to contact us through any of the
@ -146,7 +173,7 @@
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto"> <materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
<Grid VerticalAlignment="Stretch"> <Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="155" /> <RowDefinition Height="175" />
<RowDefinition Height="95" /> <RowDefinition Height="95" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -157,7 +184,8 @@
HorizontalAlignment="Center" VerticalAlignment="Center" /> HorizontalAlignment="Center" VerticalAlignment="Center" />
<StackPanel Grid.Row="0" Grid.Column="1"> <StackPanel Grid.Row="0" Grid.Column="1">
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Open Source</TextBlock> <TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Open Source</TextBlock>
<TextBlock TextWrapping="Wrap" Margin="16 0 16 8" <TextBlock Style="{StaticResource MaterialDesignTextBlock}"
TextWrapping="Wrap" Margin="16 0 16 8"
Foreground="{DynamicResource MaterialDesignBodyLight}" Foreground="{DynamicResource MaterialDesignBodyLight}"
VerticalAlignment="Top"> VerticalAlignment="Top">
This project is completely open source. If you like it and want to say thanks you could hit the GitHub Star button, This project is completely open source. If you like it and want to say thanks you could hit the GitHub Star button,
@ -188,49 +216,7 @@
</Grid> </Grid>
</materialDesign:Card> </materialDesign:Card>
</StackPanel> </StackPanel>
</ScrollViewer>
<!-- PopupBox could be nice in the future when we actually have some stuff to send ppl to -->
<!--<materialDesign:PopupBox Style="{StaticResource MaterialDesignMultiFloatingActionPopupBox}"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Margin="32" Grid.Row="1">
--><!-- add the visibility binding https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/issues/723 --><!--
<StackPanel Visibility="{Binding Path=IsPopupOpen, ElementName=MyPopupBox, Converter={StaticResource BoolToVisibilityConverter}}">
<Button ToolTip="GitHub" Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis">
<materialDesign:PackIcon Kind="Github" Height="20" Width="20" />
</Button>
<Button ToolTip="Twitter" Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis"
Background="{DynamicResource PrimaryHueMidBrush}"
Foreground="{DynamicResource PrimaryHueMidForegroundBrush}">
<materialDesign:PackIcon Kind="Twitter" />
</Button>
<Button ToolTip="Chat" Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis">
--><!-- mix up the colours by brinking in a named palette (see merged dictionaries at top) --><!--
<Button.Background>
<SolidColorBrush Color="{StaticResource GreenPrimary500}" />
</Button.Background>
<Button.Foreground>
<SolidColorBrush Color="{StaticResource GreenPrimary500Foreground}" />
</Button.Foreground>
<materialDesign:PackIcon Kind="Message" />
</Button>
<Button ToolTip="Email" Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis"
Background="{DynamicResource SecondaryHueMidBrush}"
Foreground="{DynamicResource SecondaryHueMidForegroundBrush}"
>
<materialDesign:PackIcon Kind="Email" />
</Button>
<Button ToolTip="Feel like you want to make a donation? It would be gratefully received. Click the button to donate via Pledgie."
Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis">
<Button.Background>
<SolidColorBrush Color="{StaticResource GreenPrimary200}" />
</Button.Background>
<Button.Foreground>
<SolidColorBrush Color="{StaticResource GreenPrimary200Foreground}" />
</Button.Foreground>
<materialDesign:PackIcon Kind="Gift" />
</Button>
</StackPanel> </StackPanel>
</materialDesign:PopupBox>--> </ScrollViewer>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -3,7 +3,6 @@ using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using Castle.Core.Internal;
using FluentValidation; using FluentValidation;
using Stylet; using Stylet;
@ -70,7 +69,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline.Dialogs
if (parts.Length == 1) if (parts.Length == 1)
return TimeSpan.FromSeconds(double.Parse(parts[0])); return TimeSpan.FromSeconds(double.Parse(parts[0]));
// Only milliseconds provided with a leading . // 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 // 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"; while (parts[0].Length < 3) parts[0] += "0";

View File

@ -61,6 +61,19 @@
VerticalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"
IsTabStop="False" /> IsTabStop="False" />
<Border Grid.Row="1" Visibility="{Binding SidebarViewModel.ActivatingProfile, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay, Delay=2000}">
<Border.Background>
<SolidColorBrush Color="{Binding Path=Color, Source={StaticResource MaterialDesignToolBarBackground}}" Opacity="0.5"></SolidColorBrush>
</Border.Background>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" Value="0" IsIndeterminate="True" Width="50" Height="50" Margin="20"/>
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignHeadline5TextBlock}">
Activating profile...
</TextBlock>
</StackPanel>
</Border>
<materialDesign:Snackbar Grid.Row="0" <materialDesign:Snackbar Grid.Row="0"
Grid.RowSpan="2" Grid.RowSpan="2"
x:Name="MainSnackbar" x:Name="MainSnackbar"

View File

@ -96,7 +96,7 @@
Grid.Column="1" Grid.Column="1"
Style="{StaticResource MaterialDesignBody1TextBlock}" Style="{StaticResource MaterialDesignBody1TextBlock}"
Padding="0"> Padding="0">
Robert 'Spoinky' Beekman Robert Beekman
</TextBlock> </TextBlock>
<TextBlock Grid.Column="1" <TextBlock Grid.Column="1"
Grid.Row="1" Grid.Row="1"
@ -111,7 +111,7 @@
Style="{StaticResource MaterialDesignIconForegroundButton}" Style="{StaticResource MaterialDesignIconForegroundButton}"
ToolTip="View GitHub profile" ToolTip="View GitHub profile"
Command="{s:Action OpenUrl}" Command="{s:Action OpenUrl}"
CommandParameter="https://github.com/SpoinkyNL/"> CommandParameter="https://github.com/RobertWasTaken/">
<materialDesign:PackIcon Kind="Github" Width="20" Height="20" /> <materialDesign:PackIcon Kind="Github" Width="20" Height="20" />
</Button> </Button>
</StackPanel> </StackPanel>

View File

@ -20,6 +20,7 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="200" /> <ColumnDefinition Width="200" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" TextWrapping="Wrap"> <TextBlock Grid.Column="0" TextWrapping="Wrap">
The list below shows all loaded plugins. <LineBreak /> The list below shows all loaded plugins. <LineBreak />
@ -38,7 +39,17 @@
Margin="5 0" Margin="5 0"
Text="{Binding SearchPluginInput, Delay=300, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding SearchPluginInput, Delay=300, UpdateSourceTrigger=PropertyChanged}" />
<Button Grid.Column="3" <Button Grid.Column="3" Style="{DynamicResource MaterialDesignFlatButton}"
HorizontalAlignment="Right"
Command="{s:Action OpenUrl}"
CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/plugins">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="OpenInBrowser" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Get more plugins</TextBlock>
</StackPanel>
</Button>
<Button Grid.Column="4"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Style="{StaticResource MaterialDesignRaisedButton}" Style="{StaticResource MaterialDesignRaisedButton}"
Command="{s:Action ImportPlugin}" Command="{s:Action ImportPlugin}"

View File

@ -77,6 +77,11 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
base.OnInitialActivate(); base.OnInitialActivate();
} }
public void OpenUrl(string url)
{
Core.Utilities.OpenUrl(url);
}
public async Task ImportPlugin() public async Task ImportPlugin()
{ {
VistaOpenFileDialog dialog = new() {Filter = "ZIP files (*.zip)|*.zip", Title = "Import Artemis plugin"}; VistaOpenFileDialog dialog = new() {Filter = "ZIP files (*.zip)|*.zip", Title = "Import Artemis plugin"};

View File

@ -18,6 +18,7 @@
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ArtemisSidebar.xaml" /> <ResourceDictionary Source="ArtemisSidebar.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<materialDesign:DialogHost IsTabStop="False" Focusable="False" Identifier="SidebarDialog" DialogTheme="Inherit" DialogMargin="14"> <materialDesign:DialogHost IsTabStop="False" Focusable="False" Identifier="SidebarDialog" DialogTheme="Inherit" DialogMargin="14">
@ -74,7 +75,8 @@
Margin="0 2" Margin="0 2"
ItemContainerStyle="{StaticResource SidebarListBoxItem}" ItemContainerStyle="{StaticResource SidebarListBoxItem}"
ItemsSource="{Binding SidebarScreens}" ItemsSource="{Binding SidebarScreens}"
SelectedItem="{Binding SelectedSidebarScreen}"> SelectedItem="{Binding SelectedSidebarScreen}"
IsEnabled="{Binding ActivatingProfile, Converter={StaticResource InverseBooleanConverter}}">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" /> <ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
@ -105,7 +107,11 @@
dd:DragDrop.DropHandler="{Binding}"> dd:DragDrop.DropHandler="{Binding}">
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" /> <ContentControl s:View.Model="{Binding}"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
IsTabStop="False"
IsEnabled="{Binding DataContext.ActivatingProfile, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource InverseBooleanConverter}}" />
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>

View File

@ -35,6 +35,7 @@ namespace Artemis.UI.Screens.Sidebar
private MainScreenViewModel _selectedScreen; private MainScreenViewModel _selectedScreen;
private readonly SidebarScreenViewModel<ProfileEditorViewModel> _profileEditor; private readonly SidebarScreenViewModel<ProfileEditorViewModel> _profileEditor;
private readonly DefaultDropHandler _defaultDropHandler; private readonly DefaultDropHandler _defaultDropHandler;
private bool _activatingProfile;
public SidebarViewModel(IKernel kernel, public SidebarViewModel(IKernel kernel,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
@ -96,6 +97,12 @@ namespace Artemis.UI.Screens.Sidebar
} }
} }
public bool ActivatingProfile
{
get => _activatingProfile;
set => SetAndNotify(ref _activatingProfile, value);
}
private void ActivateScreenViewModel(SidebarScreenViewModel screenViewModel) private void ActivateScreenViewModel(SidebarScreenViewModel screenViewModel)
{ {
SelectedScreen = screenViewModel.CreateInstance(_kernel); SelectedScreen = screenViewModel.CreateInstance(_kernel);
@ -155,8 +162,23 @@ namespace Artemis.UI.Screens.Sidebar
if (_profileEditorService.SuspendEditing) if (_profileEditorService.SuspendEditing)
_profileEditorService.SuspendEditing = false; _profileEditorService.SuspendEditing = false;
Task.Run(() =>
{
try
{
ActivatingProfile = true;
_profileEditorService.ChangeSelectedProfileConfiguration(profileConfiguration); _profileEditorService.ChangeSelectedProfileConfiguration(profileConfiguration);
if (profileConfiguration != null) }
finally
{
ActivatingProfile = false;
}
if (profileConfiguration == null)
return;
Execute.PostToUIThread(() =>
{ {
// Little workaround to clear the selected item in the menu, ugly but oh well // Little workaround to clear the selected item in the menu, ugly but oh well
if (_selectedSidebarScreen != _profileEditor) if (_selectedSidebarScreen != _profileEditor)
@ -166,7 +188,8 @@ namespace Artemis.UI.Screens.Sidebar
} }
SelectedSidebarScreen = _profileEditor; SelectedSidebarScreen = _profileEditor;
} });
});
} }
#region Overrides of Screen #region Overrides of Screen

View File

@ -31,14 +31,14 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
/// <inheritdoc /> /// <inheritdoc />
protected override void OnActivate() protected override void OnActivate()
{ {
_rgbService.IsRenderPaused = true; _rgbService.SetRenderPaused(true);
base.OnActivate(); base.OnActivate();
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void OnDeactivate() protected override void OnDeactivate()
{ {
_rgbService.IsRenderPaused = false; _rgbService.SetRenderPaused(false);
base.OnDeactivate(); base.OnDeactivate();
} }

View File

@ -333,7 +333,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
SurfaceDeviceViewModel device = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect).FirstOrDefault(); SurfaceDeviceViewModel device = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect).FirstOrDefault();
if (device != null) if (device != null)
{ {
_rgbService.IsRenderPaused = true; _rgbService.SetRenderPaused(true);
_mouseDragStatus = MouseDragStatus.Dragging; _mouseDragStatus = MouseDragStatus.Dragging;
// If the device is not selected, deselect others and select only this one (if shift not held) // If the device is not selected, deselect others and select only this one (if shift not held)
if (device.SelectionStatus != SelectionStatus.Selected) if (device.SelectionStatus != SelectionStatus.Selected)
@ -378,7 +378,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
} }
_mouseDragStatus = MouseDragStatus.None; _mouseDragStatus = MouseDragStatus.None;
_rgbService.IsRenderPaused = false; _rgbService.SetRenderPaused(false);
ApplySurfaceSelection(); ApplySurfaceSelection();
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
namespace Artemis.UI.Utilities namespace Artemis.UI.Utilities
{ {

File diff suppressed because it is too large Load Diff