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

Core - Moved startup arguments from CoreService to Constants

Web server - Added setting to disable the web server
Web server - Added --disable-webserver startup argument to disable the web server
UI - Fixed Artemis not bringing existing instances to foreground if already running
This commit is contained in:
Robert 2022-08-26 20:32:36 +02:00
parent 87b87a9145
commit 928d9711af
14 changed files with 516 additions and 455 deletions

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using Artemis.Core.JsonConverters; using Artemis.Core.JsonConverters;
@ -90,6 +91,11 @@ public static class Constants
/// </summary> /// </summary>
public static readonly Plugin CorePlugin = new(CorePluginInfo, new DirectoryInfo(ApplicationFolder), null); public static readonly Plugin CorePlugin = new(CorePluginInfo, new DirectoryInfo(ApplicationFolder), null);
/// <summary>
/// Gets the startup arguments provided to the application
/// </summary>
public static ReadOnlyCollection<string> StartupArguments { get; set; } = null!;
internal static readonly CorePluginFeature CorePluginFeature = new() {Plugin = CorePlugin, Profiler = CorePlugin.GetProfiler("Feature - Core")}; internal static readonly CorePluginFeature CorePluginFeature = new() {Plugin = CorePlugin, Profiler = CorePlugin.GetProfiler("Feature - Core")};
internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new() {Plugin = CorePlugin, Profiler = CorePlugin.GetProfiler("Feature - Effect Placeholder")}; internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new() {Plugin = CorePlugin, Profiler = CorePlugin.GetProfiler("Feature - Effect Placeholder")};

View File

@ -58,7 +58,6 @@ internal class CoreService : ICoreService
_scriptingService = scriptingService; _scriptingService = scriptingService;
_loggingLevel = settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Debug); _loggingLevel = settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Debug);
_frameStopWatch = new Stopwatch(); _frameStopWatch = new Stopwatch();
StartupArguments = new List<string>();
_rgbService.Surface.Updating += SurfaceOnUpdating; _rgbService.Surface.Updating += SurfaceOnUpdating;
_loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel(); _loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel();
@ -78,7 +77,7 @@ internal class CoreService : ICoreService
private void ApplyLoggingLevel() private void ApplyLoggingLevel()
{ {
string? argument = StartupArguments.FirstOrDefault(a => a.StartsWith("--logging")); string? argument = Constants.StartupArguments.FirstOrDefault(a => a.StartsWith("--logging"));
if (argument != null) if (argument != null)
{ {
// Parse the provided log level // Parse the provided log level
@ -194,7 +193,6 @@ internal class CoreService : ICoreService
public int FrameRate { get; private set; } public int FrameRate { get; private set; }
public TimeSpan FrameTime { get; private set; } public TimeSpan FrameTime { get; private set; }
public bool ProfileRenderingDisabled { get; set; } public bool ProfileRenderingDisabled { get; set; }
public List<string> StartupArguments { get; set; }
public bool IsElevated { get; set; } public bool IsElevated { get; set; }
public void Dispose() public void Dispose()
@ -217,7 +215,7 @@ internal class CoreService : ICoreService
Constants.BuildInfo.BuildNumber, Constants.BuildInfo.BuildNumber,
Constants.BuildInfo.SourceBranch Constants.BuildInfo.SourceBranch
); );
_logger.Information("Startup arguments: {args}", StartupArguments); _logger.Information("Startup arguments: {args}", Constants.StartupArguments);
_logger.Information("Elevated permissions: {perms}", IsElevated); _logger.Information("Elevated permissions: {perms}", IsElevated);
_logger.Information("Stopwatch high resolution: {perms}", Stopwatch.IsHighResolution); _logger.Information("Stopwatch high resolution: {perms}", Stopwatch.IsHighResolution);
@ -230,9 +228,9 @@ internal class CoreService : ICoreService
// Initialize the services // Initialize the services
_pluginManagementService.CopyBuiltInPlugins(); _pluginManagementService.CopyBuiltInPlugins();
_pluginManagementService.LoadPlugins(StartupArguments, IsElevated); _pluginManagementService.LoadPlugins(IsElevated);
_rgbService.ApplyPreferredGraphicsContext(StartupArguments.Contains("--force-software-render")); _rgbService.ApplyPreferredGraphicsContext(Constants.StartupArguments.Contains("--force-software-render"));
_rgbService.SetRenderPaused(false); _rgbService.SetRenderPaused(false);
OnInitialized(); OnInitialized();
} }

View File

@ -28,11 +28,6 @@ public interface ICoreService : IArtemisService, IDisposable
/// </summary> /// </summary>
bool ProfileRenderingDisabled { get; set; } bool ProfileRenderingDisabled { get; set; }
/// <summary>
/// Gets or sets a list of startup arguments
/// </summary>
List<string> StartupArguments { get; set; }
/// <summary> /// <summary>
/// Gets a boolean indicating whether Artemis is running in an elevated environment (admin permissions) /// Gets a boolean indicating whether Artemis is running in an elevated environment (admin permissions)
/// </summary> /// </summary>

View File

@ -26,7 +26,7 @@ public interface IPluginManagementService : IArtemisService, IDisposable
/// <summary> /// <summary>
/// Loads all installed plugins. If plugins already loaded this will reload them all /// Loads all installed plugins. If plugins already loaded this will reload them all
/// </summary> /// </summary>
void LoadPlugins(List<string> startupArguments, bool isElevated); void LoadPlugins(bool isElevated);
/// <summary> /// <summary>
/// Unloads all installed plugins. /// Unloads all installed plugins.

View File

@ -203,17 +203,17 @@ internal class PluginManagementService : IPluginManagementService
#region Plugins #region Plugins
public void LoadPlugins(List<string> startupArguments, bool isElevated) public void LoadPlugins(bool isElevated)
{ {
if (startupArguments.Contains("--no-plugins")) if (Constants.StartupArguments.Contains("--no-plugins"))
{ {
_logger.Warning("Artemis launched with --no-plugins, skipping the loading of plugins"); _logger.Warning("Artemis launched with --no-plugins, skipping the loading of plugins");
return; return;
} }
bool ignorePluginLock = startupArguments.Contains("--ignore-plugin-lock"); bool ignorePluginLock = Constants.StartupArguments.Contains("--ignore-plugin-lock");
bool stayElevated = startupArguments.Contains("--force-elevation"); bool stayElevated = Constants.StartupArguments.Contains("--force-elevation");
bool droppedAdmin = startupArguments.Contains("--dropped-admin"); bool droppedAdmin = Constants.StartupArguments.Contains("--dropped-admin");
if (LoadingPlugins) if (LoadingPlugins)
throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet."); throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet.");

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core.Modules; using Artemis.Core.Modules;
using EmbedIO; using EmbedIO;
@ -17,15 +18,19 @@ internal class WebServerService : IWebServerService, IDisposable
private readonly List<WebApiControllerRegistration> _controllers; private readonly List<WebApiControllerRegistration> _controllers;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly List<WebModuleRegistration> _modules; private readonly List<WebModuleRegistration> _modules;
private readonly PluginSetting<bool> _webServerEnabledSetting;
private readonly PluginSetting<int> _webServerPortSetting; private readonly PluginSetting<int> _webServerPortSetting;
private CancellationTokenSource? _cts;
public WebServerService(ILogger logger, ISettingsService settingsService, IPluginManagementService pluginManagementService) public WebServerService(ILogger logger, ICoreService coreService, ISettingsService settingsService, IPluginManagementService pluginManagementService)
{ {
_logger = logger; _logger = logger;
_controllers = new List<WebApiControllerRegistration>(); _controllers = new List<WebApiControllerRegistration>();
_modules = new List<WebModuleRegistration>(); _modules = new List<WebModuleRegistration>();
_webServerEnabledSetting = settingsService.GetSetting("WebServer.Enabled", true);
_webServerPortSetting = settingsService.GetSetting("WebServer.Port", 9696); _webServerPortSetting = settingsService.GetSetting("WebServer.Port", 9696);
_webServerEnabledSetting.SettingChanged += WebServerEnabledSettingOnSettingChanged;
_webServerPortSetting.SettingChanged += WebServerPortSettingOnSettingChanged; _webServerPortSetting.SettingChanged += WebServerPortSettingOnSettingChanged;
pluginManagementService.PluginFeatureDisabled += PluginManagementServiceOnPluginFeatureDisabled; pluginManagementService.PluginFeatureDisabled += PluginManagementServiceOnPluginFeatureDisabled;
@ -33,9 +38,9 @@ internal class WebServerService : IWebServerService, IDisposable
StartWebServer(); StartWebServer();
} }
protected virtual void OnWebServerStarting() private void WebServerEnabledSettingOnSettingChanged(object? sender, EventArgs e)
{ {
WebServerStarting?.Invoke(this, EventArgs.Empty); StartWebServer();
} }
private void WebServerPortSettingOnSettingChanged(object? sender, EventArgs e) private void WebServerPortSettingOnSettingChanged(object? sender, EventArgs e)
@ -72,14 +77,23 @@ internal class WebServerService : IWebServerService, IDisposable
public WebServer? Server { get; private set; } public WebServer? Server { get; private set; }
public PluginsModule PluginsModule { get; } public PluginsModule PluginsModule { get; }
public event EventHandler? WebServerStarting;
#region Web server managament #region Web server managament
private WebServer CreateWebServer() private WebServer CreateWebServer()
{ {
Server?.Dispose(); if (Server != null)
Server = null; {
if (_cts != null)
{
_cts.Cancel();
_cts = null;
}
Server.Dispose();
OnWebServerStopped();
Server = null;
}
WebApiModule apiModule = new("/", JsonNetSerializer); WebApiModule apiModule = new("/", JsonNetSerializer);
PluginsModule.ServerUrl = $"http://localhost:{_webServerPortSetting.Value}/"; PluginsModule.ServerUrl = $"http://localhost:{_webServerPortSetting.Value}/";
@ -112,8 +126,20 @@ internal class WebServerService : IWebServerService, IDisposable
private void StartWebServer() private void StartWebServer()
{ {
Server = CreateWebServer(); Server = CreateWebServer();
if (!_webServerEnabledSetting.Value)
return;
if (Constants.StartupArguments.Contains("--disable-webserver"))
{
_logger.Warning("Artemis launched with --disable-webserver, not enabling the webserver");
return;
}
OnWebServerStarting(); OnWebServerStarting();
Server.Start(); _cts = new CancellationTokenSource();
Server.Start(_cts.Token);
OnWebServerStarted();
} }
#endregion #endregion
@ -276,4 +302,27 @@ internal class WebServerService : IWebServerService, IDisposable
} }
#endregion #endregion
#region Events
protected virtual void OnWebServerStopped()
{
WebServerStopped?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnWebServerStarting()
{
WebServerStarting?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnWebServerStarted()
{
WebServerStarted?.Invoke(this, EventArgs.Empty);
}
public event EventHandler? WebServerStopped;
public event EventHandler? WebServerStarting;
public event EventHandler? WebServerStarted;
#endregion
} }

View File

@ -1,3 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading;
using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Windows.Ninject; using Artemis.UI.Windows.Ninject;
using Artemis.UI.Windows.Providers.Input; using Artemis.UI.Windows.Providers.Input;
@ -13,14 +21,23 @@ namespace Artemis.UI.Windows;
public class App : Application public class App : Application
{ {
private StandardKernel? _kernel;
private bool _shutDown;
// ReSharper disable NotAccessedField.Local // ReSharper disable NotAccessedField.Local
private ApplicationStateManager? _applicationStateManager; private ApplicationStateManager? _applicationStateManager;
private Mutex? _artemisMutex;
// ReSharper restore NotAccessedField.Local // ReSharper restore NotAccessedField.Local
private StandardKernel? _kernel;
public override void Initialize() public override void Initialize()
{ {
// If Artemis is already running, bring it to foreground and stop this process
if (FocusExistingInstance())
{
_shutDown = true;
Environment.Exit(1);
}
_kernel = ArtemisBootstrapper.Bootstrap(this, new WindowsModule()); _kernel = ArtemisBootstrapper.Bootstrap(this, new WindowsModule());
Program.CreateLogger(_kernel); Program.CreateLogger(_kernel);
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance; RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
@ -29,7 +46,7 @@ public class App : Application
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()
{ {
if (ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop || Design.IsDesignMode) if (ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop || Design.IsDesignMode || _shutDown)
return; return;
ArtemisBootstrapper.Initialize(); ArtemisBootstrapper.Initialize();
@ -42,4 +59,55 @@ public class App : Application
IInputService inputService = standardKernel.Get<IInputService>(); IInputService inputService = standardKernel.Get<IInputService>();
inputService.AddInputProvider(standardKernel.Get<WindowsInputProvider>()); inputService.AddInputProvider(standardKernel.Get<WindowsInputProvider>());
} }
private bool FocusExistingInstance()
{
_artemisMutex = new Mutex(true, "Artemis-3c24b502-64e6-4587-84bf-9072970e535f", out bool createdNew);
return !createdNew && RemoteFocus();
}
private bool RemoteFocus()
{
// At this point we cannot read the database yet to retrieve the web server port.
// Instead use the method external applications should use as well.
if (!File.Exists(Path.Combine(Constants.DataFolder, "webserver.txt")))
{
KillOtherInstances();
return false;
}
string url = File.ReadAllText(Path.Combine(Constants.DataFolder, "webserver.txt"));
using HttpClient client = new();
try
{
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;
}
catch (Exception)
{
KillOtherInstances();
return false;
}
}
private void KillOtherInstances()
{
// Kill everything else heh
List<Process> processes = Process.GetProcessesByName("Artemis.UI.Windows").Where(p => p.Id != Process.GetCurrentProcess().Id).ToList();
foreach (Process process in processes)
{
try
{
process.Kill(true);
}
catch (Exception)
{
// ignored
}
}
}
} }

View File

@ -3,12 +3,9 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Security.Principal; using System.Security.Principal;
using System.Threading;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Shared.Services;
using Artemis.UI.Windows.Utilities; using Artemis.UI.Windows.Utilities;
using Avalonia; using Avalonia;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
@ -19,14 +16,8 @@ namespace Artemis.UI.Windows;
public class ApplicationStateManager public class ApplicationStateManager
{ {
private readonly IWindowService _windowService;
// ReSharper disable once NotAccessedField.Local - Kept in scope to ensure it does not get released
private Mutex? _artemisMutex;
public ApplicationStateManager(IKernel kernel, string[] startupArguments) public ApplicationStateManager(IKernel kernel, string[] startupArguments)
{ {
_windowService = kernel.Get<IWindowService>();
StartupArguments = startupArguments; StartupArguments = startupArguments;
IsElevated = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); IsElevated = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
@ -51,72 +42,6 @@ public class ApplicationStateManager
public string[] StartupArguments { get; } public string[] StartupArguments { get; }
public bool IsElevated { get; } public bool IsElevated { get; }
public bool FocusExistingInstance()
{
_artemisMutex = new Mutex(true, "Artemis-3c24b502-64e6-4587-84bf-9072970e535f", out bool createdNew);
if (createdNew)
return false;
return RemoteFocus();
}
public void DisplayException(Exception e)
{
try
{
_windowService.ShowExceptionDialog("An unhandled exception occured", e);
}
catch
{
// ignored, we tried
}
}
private bool RemoteFocus()
{
// At this point we cannot read the database yet to retrieve the web server port.
// Instead use the method external applications should use as well.
if (!File.Exists(Path.Combine(Constants.DataFolder, "webserver.txt")))
{
KillOtherInstances();
return false;
}
string url = File.ReadAllText(Path.Combine(Constants.DataFolder, "webserver.txt"));
using HttpClient client = new();
try
{
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;
}
catch (Exception)
{
KillOtherInstances();
return false;
}
}
private void KillOtherInstances()
{
// Kill everything else heh
List<Process> processes = Process.GetProcessesByName("Artemis.UI.Windows").Where(p => p.Id != Process.GetCurrentProcess().Id).ToList();
foreach (Process process in processes)
{
try
{
process.Kill(true);
}
catch (Exception)
{
// ignored
}
}
}
private void UtilitiesOnRestartRequested(object? sender, RestartEventArgs e) private void UtilitiesOnRestartRequested(object? sender, RestartEventArgs e)
{ {
List<string> argsList = new(); List<string> argsList = new();

View File

@ -1,4 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive; using System.Reactive;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Ninject; using Artemis.Core.Ninject;
@ -52,6 +55,8 @@ public static class ArtemisBootstrapper
if (_application.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) if (_application.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
return; return;
Constants.StartupArguments = new ReadOnlyCollection<string>(new List<string>(desktop.Args));
// Don't shut down when the last window closes, we might still be active in the tray // Don't shut down when the last window closes, we might still be active in the tray
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown; desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
// Create the root view model that drives the UI // Create the root view model that drives the UI

View File

@ -47,12 +47,12 @@ public class MainWindow : ReactiveCoreWindow<RootViewModel>
private void OnActivated(object? sender, EventArgs e) private void OnActivated(object? sender, EventArgs e)
{ {
ViewModel.Focused(); ViewModel?.Focused();
} }
private void OnDeactivated(object? sender, EventArgs e) private void OnDeactivated(object? sender, EventArgs e)
{ {
ViewModel.Unfocused(); ViewModel?.Unfocused();
} }
private void InitializeComponent() private void InitializeComponent()

View File

@ -55,7 +55,6 @@ public class RootViewModel : ActivatableViewModelBase, IScreen, IMainWindowProvi
_sidebarVmFactory = sidebarVmFactory; _sidebarVmFactory = sidebarVmFactory;
_lifeTime = (IClassicDesktopStyleApplicationLifetime) Application.Current!.ApplicationLifetime!; _lifeTime = (IClassicDesktopStyleApplicationLifetime) Application.Current!.ApplicationLifetime!;
coreService.StartupArguments = _lifeTime.Args.ToList();
mainWindowService.ConfigureMainWindowProvider(this); mainWindowService.ConfigureMainWindowProvider(this);
DisplayAccordingToSettings(); DisplayAccordingToSettings();
@ -99,8 +98,8 @@ public class RootViewModel : ActivatableViewModelBase, IScreen, IMainWindowProvi
private void DisplayAccordingToSettings() private void DisplayAccordingToSettings()
{ {
bool autoRunning = _coreService.StartupArguments.Contains("--autorun"); bool autoRunning = Constants.StartupArguments.Contains("--autorun");
bool minimized = _coreService.StartupArguments.Contains("--minimized"); bool minimized = Constants.StartupArguments.Contains("--minimized");
bool showOnAutoRun = _settingsService.GetSetting("UI.ShowOnStartup", true).Value; bool showOnAutoRun = _settingsService.GetSetting("UI.ShowOnStartup", true).Value;
if ((autoRunning && !showOnAutoRun) || minimized) if ((autoRunning && !showOnAutoRun) || minimized)

View File

@ -13,364 +13,379 @@
x:DataType="settings:GeneralTabViewModel"> x:DataType="settings:GeneralTabViewModel">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel Margin="15" MaxWidth="1000"> <StackPanel Margin="15" MaxWidth="1000">
<!-- General settings --> <!-- General settings -->
<TextBlock Classes="h4" Margin="0 15"> <TextBlock Classes="h4" Margin="0 15">
General General
</TextBlock> </TextBlock>
<Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0"> <Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0">
<StackPanel> <StackPanel>
<StackPanel IsVisible="{CompiledBinding IsAutoRunSupported}"> <StackPanel IsVisible="{CompiledBinding IsAutoRunSupported}">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">
<TextBlock>Auto-run on startup</TextBlock> <TextBlock>Auto-run on startup</TextBlock>
</StackPanel> </StackPanel>
<ToggleSwitch Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" IsChecked="{CompiledBinding UIAutoRun.Value}" MinWidth="0" Margin="0 -10"/> <ToggleSwitch Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" IsChecked="{CompiledBinding UIAutoRun.Value}" MinWidth="0" Margin="0 -10" OnContent="Yes"
</Grid> OffContent="No" />
<Separator Classes="card-separator" /> </Grid>
<Separator Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">
<TextBlock>Hide window on auto-run</TextBlock> <TextBlock>Hide window on auto-run</TextBlock>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<ToggleSwitch IsChecked="{CompiledBinding !UIShowOnStartup.Value}" IsEnabled="{CompiledBinding UIAutoRun.Value}" MinWidth="0" Margin="0 -10"/> <ToggleSwitch IsChecked="{CompiledBinding !UIShowOnStartup.Value}" IsEnabled="{CompiledBinding UIAutoRun.Value}" MinWidth="0" Margin="0 -10" OnContent="Yes"
</StackPanel> OffContent="No" />
</Grid> </StackPanel>
<Separator Classes="card-separator" /> </Grid>
<Separator Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">
<TextBlock>Startup delay</TextBlock> <TextBlock>Startup delay</TextBlock>
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <TextBlock Classes="subtitle" TextWrapping="Wrap">
Set the amount of seconds to wait before auto-running Artemis. Set the amount of seconds to wait before auto-running Artemis.
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <TextBlock Classes="subtitle" TextWrapping="Wrap">
If some devices don't work because Artemis starts before the manufacturer's software, try increasing this value. If some devices don't work because Artemis starts before the manufacturer's software, try increasing this value.
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal"> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
<controls:NumberBox IsEnabled="{CompiledBinding UIAutoRun.Value}" Width="120"> <controls:NumberBox IsEnabled="{CompiledBinding UIAutoRun.Value}" Width="120">
<Interaction.Behaviors> <Interaction.Behaviors>
<behaviors:LostFocusNumberBoxBindingBehavior Value="{CompiledBinding UIAutoRunDelay.Value}"/> <behaviors:LostFocusNumberBoxBindingBehavior Value="{CompiledBinding UIAutoRunDelay.Value}" />
</Interaction.Behaviors> </Interaction.Behaviors>
</controls:NumberBox> </controls:NumberBox>
<TextBlock VerticalAlignment="Center" TextAlignment="Right" Width="30">sec</TextBlock> <TextBlock VerticalAlignment="Center" TextAlignment="Right" Width="30">sec</TextBlock>
</StackPanel> </StackPanel>
</Grid> </Grid>
<Separator Classes="card-separator" /> <Separator Classes="card-separator" />
</StackPanel> </StackPanel>
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">
<TextBlock> <TextBlock>
Log level Log level
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <TextBlock Classes="subtitle" TextWrapping="Wrap">
Sets the logging level, a higher logging level will result in more log files. Sets the logging level, a higher logging level will result in more log files.
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<shared:EnumComboBox Width="150" Value="{CompiledBinding CoreLoggingLevel.Value}" /> <shared:EnumComboBox Width="150" Value="{CompiledBinding CoreLoggingLevel.Value}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
<Separator Classes="card-separator" /> <Separator Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center"> <StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock> <TextBlock>
Logs Logs
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle"> <TextBlock Classes="subtitle">
Opens the directory where logs are stored. Opens the directory where logs are stored.
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Button Command="{CompiledBinding ShowLogs}" Width="150" Content="Show logs" /> <Button Command="{CompiledBinding ShowLogs}" Width="150" Content="Show logs" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</StackPanel> </StackPanel>
</Border> </Border>
<!-- Web server settings --> <!-- Web server settings -->
<TextBlock Classes="h4" Margin="0 15"> <TextBlock Classes="h4" Margin="0 15">
Web server Web server
</TextBlock> </TextBlock>
<Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0"> <Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0">
<StackPanel> <StackPanel>
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">
<TextBlock> <TextBlock>Enable web server</TextBlock>
Web server port <TextBlock Classes="subtitle" TextWrapping="Wrap">
</TextBlock> Artemis runs a local web server that can be used to externally interact with the application.
<TextBlock Classes="subtitle" TextWrapping="Wrap"> </TextBlock>
Artemis runs a local web server that can be used to externally interact with the application. <TextBlock Classes="subtitle" TextWrapping="Wrap">
</TextBlock> This web server can only be accessed by applications running on your own computer, e.g. supported games.
<TextBlock Classes="subtitle" TextWrapping="Wrap"> </TextBlock>
This web server can only be accessed by applications running on your own computer, e.g. supported games. </StackPanel>
</TextBlock> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
</StackPanel> <ToggleSwitch IsChecked="{CompiledBinding WebServerEnabled.Value}" OnContent="Yes" OffContent="No" MinWidth="0" Margin="0 -10" />
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> </StackPanel>
<controls:NumberBox Width="150"> </Grid>
<Interaction.Behaviors> <Separator Classes="card-separator" />
<behaviors:LostFocusNumberBoxBindingBehavior Value="{CompiledBinding WebServerPort.Value}"/>
</Interaction.Behaviors>
</controls:NumberBox>
</StackPanel>
</Grid>
</StackPanel>
</Border>
<!-- Update settings --> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel IsVisible="{CompiledBinding IsUpdatingSupported}"> <StackPanel Grid.Column="0">
<TextBlock Classes="h4" Margin="0 15"> <TextBlock>
Updating Web server port
</TextBlock> </TextBlock>
<Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0"> <TextBlock Classes="subtitle" TextWrapping="Wrap">
<StackPanel> If the webserver does not work you can try changing the port to one that is available.
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> </TextBlock>
<StackPanel Grid.Column="0"> </StackPanel>
<TextBlock> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
Check for updates <controls:NumberBox Width="150">
</TextBlock> <Interaction.Behaviors>
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <behaviors:LostFocusNumberBoxBindingBehavior Value="{CompiledBinding WebServerPort.Value}" />
If enabled, we'll check for updates on startup and periodically while running. </Interaction.Behaviors>
</TextBlock> </controls:NumberBox>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> </Grid>
<ToggleSwitch IsChecked="{CompiledBinding UICheckForUpdates.Value}" MinWidth="0" /> </StackPanel>
</StackPanel> </Border>
</Grid>
<Separator Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <!-- Update settings -->
<StackPanel Grid.Column="0"> <StackPanel IsVisible="{CompiledBinding IsUpdatingSupported}">
<TextBlock> <TextBlock Classes="h4" Margin="0 15">
Auto-install updates Updating
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0">
If enabled, new updates will automatically be installed. <StackPanel>
</TextBlock> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
</StackPanel> <StackPanel Grid.Column="0">
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> <TextBlock>
<ToggleSwitch IsEnabled="{CompiledBinding UICheckForUpdates.Value}" IsChecked="{CompiledBinding UIAutoUpdate.Value}" MinWidth="0" /> Check for updates
</StackPanel> </TextBlock>
</Grid> <TextBlock Classes="subtitle" TextWrapping="Wrap">
<Separator Classes="card-separator" /> If enabled, we'll check for updates on startup and periodically while running.
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<ToggleSwitch IsChecked="{CompiledBinding UICheckForUpdates.Value}" MinWidth="0" OnContent="Yes" OffContent="No" />
</StackPanel>
</Grid>
<Separator Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center"> <StackPanel Grid.Column="0">
<TextBlock> <TextBlock>
Update Auto-install updates
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle"> <TextBlock Classes="subtitle" TextWrapping="Wrap">
Use the button on the right to check for updates now. If enabled, new updates will automatically be installed.
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Button Command="{CompiledBinding CheckForUpdate}" Width="150" Content="Check now" /> <ToggleSwitch IsEnabled="{CompiledBinding UICheckForUpdates.Value}" IsChecked="{CompiledBinding UIAutoUpdate.Value}" MinWidth="0" OnContent="Yes" OffContent="No" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</StackPanel> <Separator Classes="card-separator" />
</Border>
</StackPanel>
<!-- Profile editor settings --> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<TextBlock Classes="h4" Margin="0 15"> <StackPanel Grid.Column="0" VerticalAlignment="Center">
Profile editor <TextBlock>
</TextBlock> Update
<Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0"> </TextBlock>
<StackPanel> <TextBlock Classes="subtitle">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> Use the button on the right to check for updates now.
<StackPanel Grid.Column="0"> </TextBlock>
<TextBlock> </StackPanel>
Show condition data model values <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
</TextBlock> <Button Command="{CompiledBinding CheckForUpdate}" Width="150" Content="Check now" />
<TextBlock Classes="subtitle" TextWrapping="Wrap"> </StackPanel>
While selecting a condition target, show the current values of the data model. </Grid>
</TextBlock> </StackPanel>
</StackPanel> </Border>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> </StackPanel>
<ToggleSwitch IsChecked="{CompiledBinding ProfileEditorShowDataModelValues.Value}" MinWidth="0" />
</StackPanel>
</Grid>
<Separator Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <!-- Profile editor settings -->
<StackPanel Grid.Column="0"> <TextBlock Classes="h4" Margin="0 15">
<TextBlock> Profile editor
Default brush </TextBlock>
</TextBlock> <Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0">
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <StackPanel>
Sets the default brush that is applied to new layers <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
</TextBlock> <StackPanel Grid.Column="0">
</StackPanel> <TextBlock>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> Show condition data model values
<StackPanel.Styles> </TextBlock>
<Style Selector="ComboBox.brush /template/ ContentControl#ContentPresenter"> <TextBlock Classes="subtitle" TextWrapping="Wrap">
<Setter Property="ContentTemplate"> While selecting a condition target, show the current values of the data model.
<Setter.Value> </TextBlock>
<DataTemplate DataType="{x:Type layerBrushes:LayerBrushDescriptor}"> </StackPanel>
<StackPanel Orientation="Horizontal"> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<avalonia:MaterialIcon Kind="{CompiledBinding Icon}" Height="20" Width="20" VerticalAlignment="Center" Margin="0 0 5 0"/> <ToggleSwitch IsChecked="{CompiledBinding ProfileEditorShowDataModelValues.Value}" MinWidth="0" OnContent="Yes" OffContent="No" />
<TextBlock Text="{CompiledBinding DisplayName}" VerticalAlignment="Center" /> </StackPanel>
</StackPanel> </Grid>
</DataTemplate> <Separator Classes="card-separator" />
</Setter.Value>
</Setter>
</Style>
</StackPanel.Styles>
<ComboBox Classes="brush"
Width="200"
HorizontalAlignment="Left"
Items="{CompiledBinding LayerBrushDescriptors}"
SelectedItem="{CompiledBinding SelectedLayerBrushDescriptor}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type layerBrushes:LayerBrushDescriptor}">
<Grid ColumnDefinitions="30,*" RowDefinitions="Auto,Auto">
<avalonia:MaterialIcon Grid.Row="0"
Grid.RowSpan="2"
Kind="{CompiledBinding Icon}"
Height="20"
Width="20"
VerticalAlignment="Center"
HorizontalAlignment="Left" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{CompiledBinding DisplayName}" TextWrapping="Wrap" MaxWidth="350" />
<TextBlock Classes="subtitle" Grid.Row="1" Grid.Column="1" Text="{CompiledBinding Description}" TextWrapping="Wrap" MaxWidth="350" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Grid>
</StackPanel>
</Border>
<!-- Rendering settings --> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<TextBlock Classes="h4" Margin="0 15"> <StackPanel Grid.Column="0">
Rendering <TextBlock>
</TextBlock> Default brush
<Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0"> </TextBlock>
<StackPanel> <TextBlock Classes="subtitle" TextWrapping="Wrap">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> Sets the default brush that is applied to new layers
<StackPanel Grid.Column="0"> </TextBlock>
<TextBlock> </StackPanel>
Preferred render method <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
</TextBlock> <StackPanel.Styles>
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <Style Selector="ComboBox.brush /template/ ContentControl#ContentPresenter">
Software-based rendering is done purely on the CPU while Vulkan uses GPU-acceleration. <Setter Property="ContentTemplate">
</TextBlock> <Setter.Value>
</StackPanel> <DataTemplate DataType="{x:Type layerBrushes:LayerBrushDescriptor}">
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> <StackPanel Orientation="Horizontal">
<ComboBox Width="150" <avalonia:MaterialIcon Kind="{CompiledBinding Icon}" Height="20" Width="20" VerticalAlignment="Center" Margin="0 0 5 0" />
SelectedItem="{CompiledBinding CorePreferredGraphicsContext.Value}" <TextBlock Text="{CompiledBinding DisplayName}" VerticalAlignment="Center" />
Items="{CompiledBinding GraphicsContexts}"/> </StackPanel>
</StackPanel> </DataTemplate>
</Grid> </Setter.Value>
<Separator Classes="card-separator" /> </Setter>
</Style>
</StackPanel.Styles>
<ComboBox Classes="brush"
Width="200"
HorizontalAlignment="Left"
Items="{CompiledBinding LayerBrushDescriptors}"
SelectedItem="{CompiledBinding SelectedLayerBrushDescriptor}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type layerBrushes:LayerBrushDescriptor}">
<Grid ColumnDefinitions="30,*" RowDefinitions="Auto,Auto">
<avalonia:MaterialIcon Grid.Row="0"
Grid.RowSpan="2"
Kind="{CompiledBinding Icon}"
Height="20"
Width="20"
VerticalAlignment="Center"
HorizontalAlignment="Left" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{CompiledBinding DisplayName}" TextWrapping="Wrap" MaxWidth="350" />
<TextBlock Classes="subtitle" Grid.Row="1" Grid.Column="1" Text="{CompiledBinding Description}" TextWrapping="Wrap" MaxWidth="350" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Grid>
</StackPanel>
</Border>
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <!-- Rendering settings -->
<StackPanel Grid.Column="0"> <TextBlock Classes="h4" Margin="0 15">
<TextBlock> Rendering
Render scale </TextBlock>
</TextBlock> <Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0">
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <StackPanel>
Sets the resolution Artemis renders at, higher scale means more CPU-usage, especially on large surfaces. <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
</TextBlock> <StackPanel Grid.Column="0">
</StackPanel> <TextBlock>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> Preferred render method
<ComboBox Width="150" </TextBlock>
SelectedItem="{CompiledBinding SelectedRenderScale}" <TextBlock Classes="subtitle" TextWrapping="Wrap">
Items="{CompiledBinding RenderScales}"> Software-based rendering is done purely on the CPU while Vulkan uses GPU-acceleration.
<ComboBox.ItemTemplate> </TextBlock>
<DataTemplate> </StackPanel>
<TextBlock Text="{CompiledBinding Display}" /> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
</DataTemplate> <ComboBox Width="150"
</ComboBox.ItemTemplate> SelectedItem="{CompiledBinding CorePreferredGraphicsContext.Value}"
</ComboBox> Items="{CompiledBinding GraphicsContexts}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
<Separator Classes="card-separator" /> <Separator Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">
<TextBlock> <TextBlock>
Target frame rate Render scale
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle" TextWrapping="Wrap"> <TextBlock Classes="subtitle" TextWrapping="Wrap">
Sets the FPS Artemis tries to render at, higher FPS means more CPU-usage but smoother animations. Sets the resolution Artemis renders at, higher scale means more CPU-usage, especially on large surfaces.
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle" TextWrapping="Wrap"> </StackPanel>
The options past 45 FPS are mostly useless unless you are using a custom device. <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
</TextBlock> <ComboBox Width="150"
</StackPanel> SelectedItem="{CompiledBinding SelectedRenderScale}"
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> Items="{CompiledBinding RenderScales}">
<ComboBox Width="150" <ComboBox.ItemTemplate>
SelectedItem="{CompiledBinding SelectedTargetFrameRate}" <DataTemplate>
Items="{CompiledBinding TargetFrameRates}"> <TextBlock Text="{CompiledBinding Display}" />
<ComboBox.ItemTemplate> </DataTemplate>
<DataTemplate> </ComboBox.ItemTemplate>
<TextBlock Text="{CompiledBinding Display}" /> </ComboBox>
</DataTemplate> </StackPanel>
</ComboBox.ItemTemplate> </Grid>
</ComboBox> <Separator Classes="card-separator" />
</StackPanel>
</Grid>
</StackPanel>
</Border>
<!-- Tools --> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<TextBlock Classes="h4" Margin="0 15"> <StackPanel Grid.Column="0">
Tools <TextBlock>
</TextBlock> Target frame rate
<Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0"> </TextBlock>
<StackPanel> <TextBlock Classes="subtitle" TextWrapping="Wrap">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> Sets the FPS Artemis tries to render at, higher FPS means more CPU-usage but smoother animations.
<StackPanel Grid.Column="0" VerticalAlignment="Center"> </TextBlock>
<TextBlock> <TextBlock Classes="subtitle" TextWrapping="Wrap">
Setup wizard The options past 45 FPS are mostly useless unless you are using a custom device.
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle"> </StackPanel>
Opens the startup wizard usually shown when Artemis first starts. <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
</TextBlock> <ComboBox Width="150"
</StackPanel> SelectedItem="{CompiledBinding SelectedTargetFrameRate}"
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> Items="{CompiledBinding TargetFrameRates}">
<Button Command="{CompiledBinding ShowSetupWizard}" Width="150" Content="Show wizard" /> <ComboBox.ItemTemplate>
</StackPanel> <DataTemplate>
</Grid> <TextBlock Text="{CompiledBinding Display}" />
<Separator Classes="card-separator" /> </DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Grid>
</StackPanel>
</Border>
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <!-- Tools -->
<StackPanel Grid.Column="0" VerticalAlignment="Center"> <TextBlock Classes="h4" Margin="0 15">
<TextBlock> Tools
Debugger </TextBlock>
</TextBlock> <Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0">
<TextBlock Classes="subtitle"> <StackPanel>
Use the debugger to see the raw image Artemis is rendering on the surface. <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
</TextBlock> <StackPanel Grid.Column="0" VerticalAlignment="Center">
</StackPanel> <TextBlock>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> Setup wizard
<Button Command="{CompiledBinding ShowDebugger}" Width="150" Content="Show debugger" /> </TextBlock>
</StackPanel> <TextBlock Classes="subtitle">
</Grid> Opens the startup wizard usually shown when Artemis first starts.
<Separator Classes="card-separator" /> </TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Button Command="{CompiledBinding ShowSetupWizard}" Width="150" Content="Show wizard" />
</StackPanel>
</Grid>
<Separator Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto"> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center"> <StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock> <TextBlock>
Application files Debugger
</TextBlock> </TextBlock>
<TextBlock Classes="subtitle"> <TextBlock Classes="subtitle">
Opens the directory where application files like plugins and settings are stored. Use the debugger to see the raw image Artemis is rendering on the surface.
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Button Command="{CompiledBinding ShowDataFolder}" Width="150" Content="Show app files" /> <Button Command="{CompiledBinding ShowDebugger}" Width="150" Content="Show debugger" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</StackPanel> <Separator Classes="card-separator" />
</Border>
</StackPanel> <Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
</ScrollViewer> <StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock>
Application files
</TextBlock>
<TextBlock Classes="subtitle">
Opens the directory where application files like plugins and settings are stored.
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Button Command="{CompiledBinding ShowDataFolder}" Width="150" Content="Show app files" />
</StackPanel>
</Grid>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</UserControl> </UserControl>

View File

@ -149,6 +149,7 @@ public class GeneralTabViewModel : ActivatableViewModelBase
public PluginSetting<string> CorePreferredGraphicsContext => _settingsService.GetSetting("Core.PreferredGraphicsContext", "Software"); public PluginSetting<string> CorePreferredGraphicsContext => _settingsService.GetSetting("Core.PreferredGraphicsContext", "Software");
public PluginSetting<double> CoreRenderScale => _settingsService.GetSetting("Core.RenderScale", 0.25); public PluginSetting<double> CoreRenderScale => _settingsService.GetSetting("Core.RenderScale", 0.25);
public PluginSetting<int> CoreTargetFrameRate => _settingsService.GetSetting("Core.TargetFrameRate", 30); public PluginSetting<int> CoreTargetFrameRate => _settingsService.GetSetting("Core.TargetFrameRate", 30);
public PluginSetting<bool> WebServerEnabled => _settingsService.GetSetting("WebServer.Enabled", true);
public PluginSetting<int> WebServerPort => _settingsService.GetSetting("WebServer.Port", 9696); public PluginSetting<int> WebServerPort => _settingsService.GetSetting("WebServer.Port", 9696);
private void ExecuteShowLogs() private void ExecuteShowLogs()

View File

@ -17,7 +17,7 @@ public class SaturateNode : Node
#region Constructors #region Constructors
public SaturateNode() public SaturateNode()
: base("Clamp", "Clamps the value to be in between 0 and 1") : base("Saturate", "Clamps the value to be in between 0 and 1")
{ {
Value = CreateInputPin<Numeric>(); Value = CreateInputPin<Numeric>();