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

Merge branch 'bitmapbrush'

This commit is contained in:
Robert 2019-12-11 19:47:57 +01:00
commit c6064986c5
16 changed files with 406 additions and 123 deletions

View File

@ -160,7 +160,7 @@
<Compile Include="Extensions\DirectoryInfoExtensions.cs" /> <Compile Include="Extensions\DirectoryInfoExtensions.cs" />
<Compile Include="Extensions\DoubleExtensions.cs" /> <Compile Include="Extensions\DoubleExtensions.cs" />
<Compile Include="Extensions\FloatExtensions.cs" /> <Compile Include="Extensions\FloatExtensions.cs" />
<Compile Include="Extensions\RgbColorExtensions.cs" /> <Compile Include="Extensions\SKColorExtensions.cs" />
<Compile Include="Extensions\RgbDeviceExtensions.cs" /> <Compile Include="Extensions\RgbDeviceExtensions.cs" />
<Compile Include="Extensions\RgbRectangleExtensions.cs" /> <Compile Include="Extensions\RgbRectangleExtensions.cs" />
<Compile Include="Extensions\TypeExtensions.cs" /> <Compile Include="Extensions\TypeExtensions.cs" />
@ -194,6 +194,7 @@
<Compile Include="Models\Profile\Profile.cs" /> <Compile Include="Models\Profile\Profile.cs" />
<Compile Include="Ninject\CoreModule.cs" /> <Compile Include="Ninject\CoreModule.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RGB.NET\BitmapBrush.cs" />
<Compile Include="RGB.NET\GraphicsDecorator.cs" /> <Compile Include="RGB.NET\GraphicsDecorator.cs" />
<Compile Include="Services\DeviceService.cs" /> <Compile Include="Services\DeviceService.cs" />
<Compile Include="Services\Interfaces\ILayerService.cs" /> <Compile Include="Services\Interfaces\ILayerService.cs" />

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Drawing;
using Artemis.Core.RGB.NET; using Artemis.Core.RGB.NET;
using RGB.NET.Core; using RGB.NET.Core;
@ -7,13 +6,13 @@ namespace Artemis.Core.Events
{ {
public class FrameRenderedEventArgs : EventArgs public class FrameRenderedEventArgs : EventArgs
{ {
public FrameRenderedEventArgs(GraphicsDecorator graphicsDecorator, RGBSurface rgbSurface) public FrameRenderedEventArgs(BitmapBrush bitmapBrush, RGBSurface rgbSurface)
{ {
GraphicsDecorator = graphicsDecorator; BitmapBrush = bitmapBrush;
RgbSurface = rgbSurface; RgbSurface = rgbSurface;
} }
public GraphicsDecorator GraphicsDecorator { get; } public BitmapBrush BitmapBrush { get; }
public RGBSurface RgbSurface { get; } public RGBSurface RgbSurface { get; }
} }
} }

View File

@ -1,14 +0,0 @@
using RGB.NET.Core;
using Color = System.Windows.Media.Color;
namespace Artemis.Core.Extensions
{
public static class RgbColorExtensions
{
public static Color ToMediaColor(this global::RGB.NET.Core.Color color)
{
var (_, r, g, b) = color.GetRGBBytes();
return Color.FromRgb(r, g, b);
}
}
}

View File

@ -0,0 +1,14 @@
using RGB.NET.Core;
using SkiaSharp;
namespace Artemis.Core.Extensions
{
// ReSharper disable once InconsistentNaming - I didn't come up with SKColor
public static class SKColorExtensions
{
public static Color ToRgbColor(this SKColor color)
{
return new Color(color.Alpha, color.Red, color.Green, color.Blue);
}
}
}

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Artemis.Core.Extensions;
using RGB.NET.Core;
using SkiaSharp;
namespace Artemis.Core.RGB.NET
{
public class BitmapBrush : AbstractDecoratable<IBrushDecorator>, IBrush, IDisposable
{
#region Constructors
public BitmapBrush(Scale scale)
{
Scale = scale;
}
#endregion
#region Properties & Fields
/// <inheritdoc />
public bool IsEnabled { get; set; } = true;
/// <inheritdoc />
public BrushCalculationMode BrushCalculationMode { get; set; } = BrushCalculationMode.Absolute;
/// <inheritdoc />
public double Brightness { get; set; }
/// <inheritdoc />
public double Opacity { get; set; }
/// <inheritdoc />
public IList<IColorCorrection> ColorCorrections { get; } = new List<IColorCorrection>();
/// <inheritdoc />
public Rectangle RenderedRectangle { get; private set; }
/// <inheritdoc />
public Dictionary<BrushRenderTarget, Color> RenderedTargets { get; } = new Dictionary<BrushRenderTarget, Color>();
public Scale Scale { get; set; }
public SKBitmap Bitmap { get; private set; }
#endregion
#region Methods
/// <inheritdoc />
public virtual void PerformRender(Rectangle rectangle, IEnumerable<BrushRenderTarget> renderTargets)
{
if (RenderedRectangle != rectangle || RenderedScale != Scale)
Bitmap = null;
RenderedRectangle = rectangle;
RenderedScale = Scale;
RenderedTargets.Clear();
if (Bitmap == null)
CreateBitmap(RenderedRectangle);
foreach (var renderTarget in renderTargets)
{
// TODO: Right now the sample size is 1, make this configurable to something higher and average the samples out
var scaledLocation = renderTarget.Point * Scale;
if (scaledLocation.X < Bitmap.Width && scaledLocation.Y < Bitmap.Height)
RenderedTargets[renderTarget] = Bitmap.GetPixel(RoundToInt(scaledLocation.X), RoundToInt(scaledLocation.Y)).ToRgbColor();
}
}
public Scale RenderedScale { get; private set; }
private void CreateBitmap(Rectangle rectangle)
{
// TODO: Test this max size, it applied to System.Drawing.Bitmap but SKBitmap might scale better or worse
var width = Math.Min((rectangle.Location.X + rectangle.Size.Width) * Scale.Horizontal, 4096);
var height = Math.Min((rectangle.Location.Y + rectangle.Size.Height) * Scale.Vertical, 4096);
Bitmap = new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt()));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int RoundToInt(double number)
{
return (int) Math.Round(number, MidpointRounding.AwayFromZero);
}
/// <inheritdoc />
public virtual void PerformFinalize()
{
}
public void Dispose()
{
Bitmap?.Dispose();
}
#endregion
}
}

View File

@ -22,7 +22,7 @@ namespace Artemis.Core.RGB.NET
var height = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.Y + l.AbsoluteLedRectangle.Size.Height) * scale, 4096); var height = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.Y + l.AbsoluteLedRectangle.Size.Height) * scale, 4096);
Bitmap = new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt())); Bitmap = new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt()));
} }
public SKBitmap Bitmap { get; private set; } public SKBitmap Bitmap { get; private set; }
public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color)

View File

@ -89,14 +89,17 @@ namespace Artemis.Core.Services
module.Update(args.DeltaTime); module.Update(args.DeltaTime);
} }
// If there is no ready graphics decorator, skip the frame // If there is no ready bitmap brush, skip the frame
lock (_rgbService.GraphicsDecorator) if (_rgbService.BitmapBrush == null)
return;
lock (_rgbService.BitmapBrush)
{ {
if (_rgbService.GraphicsDecorator?.Bitmap == null) if (_rgbService.BitmapBrush.Bitmap == null)
return; return;
// Render all active modules // Render all active modules
using (var canvas = new SKCanvas(_rgbService.GraphicsDecorator.Bitmap)) using (var canvas = new SKCanvas(_rgbService.BitmapBrush.Bitmap))
{ {
canvas.Clear(new SKColor(0, 0, 0)); canvas.Clear(new SKColor(0, 0, 0));
lock (_modules) lock (_modules)
@ -117,7 +120,7 @@ namespace Artemis.Core.Services
private void SurfaceOnUpdated(UpdatedEventArgs args) private void SurfaceOnUpdated(UpdatedEventArgs args)
{ {
OnFrameRendered(new FrameRenderedEventArgs(_rgbService.GraphicsDecorator, _rgbService.Surface)); OnFrameRendered(new FrameRenderedEventArgs(_rgbService.BitmapBrush, _rgbService.Surface));
} }
protected virtual void OnFrameRendering(FrameRenderingEventArgs e) protected virtual void OnFrameRendering(FrameRenderingEventArgs e)

View File

@ -9,7 +9,7 @@ namespace Artemis.Core.Services.Interfaces
public interface IRgbService : IArtemisService public interface IRgbService : IArtemisService
{ {
RGBSurface Surface { get; set; } RGBSurface Surface { get; set; }
GraphicsDecorator GraphicsDecorator { get; } BitmapBrush BitmapBrush { get; }
IReadOnlyCollection<IRGBDevice> LoadedDevices { get; } IReadOnlyCollection<IRGBDevice> LoadedDevices { get; }
void AddDeviceProvider(IRGBDeviceProvider deviceProvider); void AddDeviceProvider(IRGBDeviceProvider deviceProvider);
@ -25,6 +25,6 @@ namespace Artemis.Core.Services.Interfaces
/// </summary> /// </summary>
event EventHandler<DeviceEventArgs> DeviceReloaded; event EventHandler<DeviceEventArgs> DeviceReloaded;
void UpdateGraphicsDecorator(); void UpdateSurfaceLedGroup();
} }
} }

View File

@ -21,7 +21,7 @@ namespace Artemis.Core.Services
private readonly PluginSetting<double> _renderScaleSetting; private readonly PluginSetting<double> _renderScaleSetting;
private readonly PluginSetting<int> _targetFrameRateSetting; private readonly PluginSetting<int> _targetFrameRateSetting;
private readonly TimerUpdateTrigger _updateTrigger; private readonly TimerUpdateTrigger _updateTrigger;
private ListLedGroup _background; private ListLedGroup _surfaceLedGroup;
internal RgbService(ILogger logger, ISettingsService settingsService) internal RgbService(ILogger logger, ISettingsService settingsService)
{ {
@ -30,7 +30,6 @@ namespace Artemis.Core.Services
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25); _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25);
Surface = RGBSurface.Instance; Surface = RGBSurface.Instance;
GraphicsDecorator = new GraphicsDecorator(new ListLedGroup(), 1);
// Let's throw these for now // Let's throw these for now
Surface.Exception += SurfaceOnException; Surface.Exception += SurfaceOnException;
@ -44,7 +43,7 @@ namespace Artemis.Core.Services
/// <inheritdoc /> /// <inheritdoc />
public RGBSurface Surface { get; set; } public RGBSurface Surface { get; set; }
public GraphicsDecorator GraphicsDecorator { get; private set; } public BitmapBrush BitmapBrush { get; private set; }
public IReadOnlyCollection<IRGBDevice> LoadedDevices => _loadedDevices.AsReadOnly(); public IReadOnlyCollection<IRGBDevice> LoadedDevices => _loadedDevices.AsReadOnly();
@ -57,7 +56,7 @@ namespace Artemis.Core.Services
_logger.Warning("RgbDevice provider {deviceProvider} has no devices", deviceProvider.GetType().Name); _logger.Warning("RgbDevice provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
return; return;
} }
foreach (var surfaceDevice in deviceProvider.Devices) foreach (var surfaceDevice in deviceProvider.Devices)
{ {
if (!_loadedDevices.Contains(surfaceDevice)) if (!_loadedDevices.Contains(surfaceDevice))
@ -80,7 +79,7 @@ namespace Artemis.Core.Services
private void RenderScaleSettingOnSettingChanged(object sender, EventArgs e) private void RenderScaleSettingOnSettingChanged(object sender, EventArgs e)
{ {
UpdateGraphicsDecorator(); UpdateSurfaceLedGroup();
} }
private void TargetFrameRateSettingOnSettingChanged(object sender, EventArgs e) private void TargetFrameRateSettingOnSettingChanged(object sender, EventArgs e)
@ -99,23 +98,28 @@ namespace Artemis.Core.Services
public event EventHandler<DeviceEventArgs> DeviceLoaded; public event EventHandler<DeviceEventArgs> DeviceLoaded;
public event EventHandler<DeviceEventArgs> DeviceReloaded; public event EventHandler<DeviceEventArgs> DeviceReloaded;
public void UpdateGraphicsDecorator() public void UpdateSurfaceLedGroup()
{ {
lock (GraphicsDecorator) if (_surfaceLedGroup == null)
{ {
// Clean up the old background if present // Apply the application wide brush and decorator
if (_background != null) BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value));
{ _surfaceLedGroup = new ListLedGroup(Surface.Leds) { Brush = BitmapBrush };
_background.Brush?.RemoveAllDecorators(); return;
_background.Detach(); }
}
lock (_surfaceLedGroup)
{
// Clean up the old background
_surfaceLedGroup.Detach();
// Apply the application wide brush and decorator // Apply the application wide brush and decorator
_background = new ListLedGroup(Surface.Leds) {Brush = new SolidColorBrush(new Color(255, 255, 255, 255))}; BitmapBrush.Scale = new Scale(_renderScaleSetting.Value);
GraphicsDecorator = new GraphicsDecorator(_background, _renderScaleSetting.Value); _surfaceLedGroup = new ListLedGroup(Surface.Leds) { Brush = BitmapBrush };
_background.Brush.RemoveAllDecorators(); }
lock (BitmapBrush)
_background.Brush.AddDecorator(GraphicsDecorator); {
} }
} }

View File

@ -93,7 +93,7 @@ namespace Artemis.Core.Services.Storage
} }
// Update the RGB service's graphics decorator to work with the new surface entity // Update the RGB service's graphics decorator to work with the new surface entity
_rgbService.UpdateGraphicsDecorator(); _rgbService.UpdateSurfaceLedGroup();
OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurface)); OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurface));
} }
@ -111,7 +111,7 @@ namespace Artemis.Core.Services.Storage
} }
_surfaceRepository.Save(surface.SurfaceEntity); _surfaceRepository.Save(surface.SurfaceEntity);
_rgbService.UpdateGraphicsDecorator(); _rgbService.UpdateSurfaceLedGroup();
OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surface)); OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surface));
} }

View File

@ -268,6 +268,7 @@ namespace Artemis.Plugins.LayerElements.Noise
return value * NORM_2D; return value * NORM_2D;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double Evaluate(double x, double y, double z) public double Evaluate(double x, double y, double z)
{ {
var stretchOffset = (x + y + z) * STRETCH_3D; var stretchOffset = (x + y + z) * STRETCH_3D;

View File

@ -22,6 +22,9 @@
<QuadraticEase EasingMode="EaseInOut" /> <QuadraticEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction> </DoubleAnimation.EasingFunction>
</DoubleAnimation> </DoubleAnimation>
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0.5" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</BeginStoryboard> </BeginStoryboard>
</DataTrigger.EnterActions> </DataTrigger.EnterActions>

View File

@ -40,26 +40,33 @@ namespace Artemis.UI.Screens.Settings.Debug
{ {
Execute.PostToUIThread(() => Execute.PostToUIThread(() =>
{ {
if (e.GraphicsDecorator.Bitmap == null) if (e.BitmapBrush.Bitmap == null)
return; return;
if (!(CurrentFrame is WriteableBitmap writeableBitmap)) if (!(CurrentFrame is WriteableBitmap writeableBitmap))
{ {
CurrentFrame = e.GraphicsDecorator.Bitmap.ToWriteableBitmap(); CurrentFrame = e.BitmapBrush.Bitmap.ToWriteableBitmap();
return; return;
} }
using (var skiaImage = SKImage.FromPixels(e.GraphicsDecorator.Bitmap.PeekPixels())) try
{ {
var info = new SKImageInfo(skiaImage.Width, skiaImage.Height); using (var skiaImage = SKImage.FromPixels(e.BitmapBrush.Bitmap.PeekPixels()))
writeableBitmap.Lock();
using (var pixmap = new SKPixmap(info, writeableBitmap.BackBuffer, writeableBitmap.BackBufferStride))
{ {
skiaImage.ReadPixels(pixmap, 0, 0); var info = new SKImageInfo(skiaImage.Width, skiaImage.Height);
} writeableBitmap.Lock();
using (var pixmap = new SKPixmap(info, writeableBitmap.BackBuffer, writeableBitmap.BackBufferStride))
{
skiaImage.ReadPixels(pixmap, 0, 0);
}
writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight)); writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight));
writeableBitmap.Unlock(); writeableBitmap.Unlock();
}
}
catch (AccessViolationException)
{
// oops
} }
}); });
} }

View File

@ -5,8 +5,10 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:xaml="https://github.com/canton7/Stylet" xmlns:xaml="https://github.com/canton7/Stylet"
xmlns:settings="clr-namespace:Artemis.UI.Screens.Settings"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance screens:SettingsViewModel}" d:DataContext="{d:DesignInstance settings:SettingsViewModel}"
d:DesignHeight="600" d:DesignWidth="600"> d:DesignHeight="600" d:DesignWidth="600">
<UserControl.Resources> <UserControl.Resources>
<ResourceDictionary> <ResourceDictionary>
@ -16,71 +18,206 @@
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<ScrollViewer> <TabControl Style="{StaticResource MaterialDesignTabControl}">
<StackPanel Margin="16"> <TabItem Header="GENERAL" TextElement.Foreground="{DynamicResource MaterialDesignBody}">
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">General</TextBlock> <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<StackPanel> <StackPanel Margin="15" MaxWidth="800">
<TextBlock>General settings like start up with Windows etc.</TextBlock> <!-- General settings -->
<Grid> <TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}" Margin="0 15">General</TextBlock>
<Grid.RowDefinitions> <materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch" Margin="0,0,5,0">
<RowDefinition /> <StackPanel Margin="15">
<RowDefinition /> <Grid>
</Grid.RowDefinitions> <Grid.RowDefinitions>
<Grid.ColumnDefinitions> <RowDefinition />
<ColumnDefinition /> <RowDefinition />
<ColumnDefinition /> </Grid.RowDefinitions>
</Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">Start up with Windows</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" ToolTip="Default ToggleButton Style" />
</StackPanel>
</Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<TextBlock VerticalAlignment="Bottom" Grid.Row="0" Grid.Column="0">Render scale</TextBlock> <Grid>
<Slider Minimum="0.10" <Grid.RowDefinitions>
Maximum="1" <RowDefinition />
TickFrequency="0.05" <RowDefinition />
Grid.Row="1" </Grid.RowDefinitions>
Grid.Column="0" <Grid.ColumnDefinitions>
Style="{StaticResource MaterialDesignDiscreteSlider}" <ColumnDefinition Width="*" />
ToolTip="MaterialDesignDiscreteSlider" <ColumnDefinition Width="Auto" />
Value="{Binding RenderScale}" /> </Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">Start up with Windows minimized</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" ToolTip="Default ToggleButton Style" />
</StackPanel>
</Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<TextBlock VerticalAlignment="Bottom" Grid.Row="0" Grid.Column="1">Target framerate</TextBlock> <Grid>
<Slider Minimum="5" <Grid.RowDefinitions>
Maximum="60" <RowDefinition />
Grid.Row="1" <RowDefinition />
Grid.Column="1" </Grid.RowDefinitions>
Style="{StaticResource MaterialDesignDiscreteSlider}" <Grid.ColumnDefinitions>
ToolTip="MaterialDesignDiscreteSlider" <ColumnDefinition Width="*" />
Value="{Binding TargetFrameRate}" /> <ColumnDefinition Width="Auto" />
</Grid> </Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">Debugger</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}">
Use the debugger to see the raw image Artemis is rendering on the surface.
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowDebugger}">
SHOW DEBUGGER
</Button>
</StackPanel>
</Grid>
</StackPanel>
</materialDesign:Card>
<Button Command="{s:Action ShowDebugger}" Style="{StaticResource MaterialDesignRaisedButton}" <!-- Rendering settings -->
HorizontalAlignment="Left" Margin="0, 10, 0, 0"> <TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}" Margin="0 15">Rendering</TextBlock>
Show debugger <materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch" Margin="0,0,5,0">
</Button> <StackPanel Margin="15">
</StackPanel> <Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">Render scale</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
Sets the resolution Artemis renders at, higher scale means more CPU-usage, especially on large surfaces.
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<ComboBox Width="80" SelectedItem="{Binding SelectedRenderScale}" ItemsSource="{Binding RenderScales}" DisplayMemberPath="Item1"/>
</StackPanel>
</Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">Devices</TextBlock> <Grid>
<Grid.RowDefinitions>
<TextBlock>A list of devices and options to disable them</TextBlock> <RowDefinition />
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="0 12 0 0"> <RowDefinition />
<ItemsControl ItemsSource="{Binding DeviceSettingsViewModels}"> </Grid.RowDefinitions>
<ItemsControl.ItemsPanel> <Grid.ColumnDefinitions>
<ItemsPanelTemplate> <ColumnDefinition Width="*" />
<WrapPanel /> <ColumnDefinition Width="Auto" />
</ItemsPanelTemplate> </Grid.ColumnDefinitions>
</ItemsControl.ItemsPanel> <StackPanel Grid.Column="0">
<ItemsControl.ItemTemplate> <TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">Target framerate</TextBlock>
<DataTemplate> <TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
<ContentControl xaml:View.Model="{Binding}" Margin="5" HorizontalAlignment="Left" Sets the FPS Artemis tries to render at, higher FPS means more CPU-usage but smoother animations.
VerticalAlignment="Top" /> </TextBlock>
</DataTemplate> </StackPanel>
</ItemsControl.ItemTemplate> <StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
</ItemsControl> <ComboBox Width="80" SelectedItem="{Binding SelectedTargetFrameRate}" ItemsSource="{Binding TargetFrameRates}" DisplayMemberPath="Item1"/>
</StackPanel>
</Grid>
</StackPanel>
</materialDesign:Card>
</StackPanel>
</ScrollViewer> </ScrollViewer>
</TabItem>
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">Plugins</TextBlock> <TabItem Header="PLUGINS" TextElement.Foreground="{DynamicResource MaterialDesignBody}">
<Grid> <DockPanel Margin="15">
<TextBlock>A list of plugins and options to disable them</TextBlock> <TextBlock DockPanel.Dock="Top">Below you view and manage your plugins. To find and install new plugins use the workshop (TODO).</TextBlock>
</Grid> <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
</StackPanel> <DataGrid Margin="0 8 0 0"
</ScrollViewer> ItemsSource="{Binding Items3}"
CanUserSortColumns="True"
CanUserAddRows="False"
AutoGenerateColumns="False"
materialDesign:DataGridAssist.CellPadding="13 8 8 8"
materialDesign:DataGridAssist.ColumnHeaderPadding="8">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsSelected}"
ElementStyle="{StaticResource MaterialDesignDataGridCheckBoxColumnStyle}"
EditingElementStyle="{StaticResource MaterialDesignDataGridCheckBoxColumnEditingStyle}">
<DataGridCheckBoxColumn.Header>
<!--padding to allow hit test to pass thru for sorting -->
<Border Background="Transparent" Padding="6 0 6 0" HorizontalAlignment="Center">
<CheckBox HorizontalAlignment="Center"
DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext}"
IsChecked="{Binding IsAllItems3Selected}" />
</Border>
</DataGridCheckBoxColumn.Header>
</DataGridCheckBoxColumn>
<DataGridTextColumn Binding="{Binding Code}" Header="Code" EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnEditingStyle}" />
<!-- if you want to use the pop up style (MaterialDesignDataGridTextColumnPopupEditingStyle), you must use MaterialDataGridTextColumn -->
<materialDesign:MaterialDataGridTextColumn Binding="{Binding Name}"
Header="Name"
EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}" />
<!-- set a max length to get an indicator in the editor -->
<materialDesign:MaterialDataGridTextColumn Binding="{Binding Description}"
Header="Description"
MaxLength="255"
EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}" />
<materialDesign:MaterialDataGridTextColumn Binding="{Binding Numeric}"
Header="Number with long header"
Width="120"
EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding}" TextAlignment="Right" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.HeaderStyle>
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</DataGridTextColumn.ElementStyle>
</materialDesign:MaterialDataGridTextColumn>
<!-- use custom combo box column to get better combos. Use ItemsSourceBinding as your binding template to be applied to each combo -->
<materialDesign:MaterialDataGridComboBoxColumn Header="Food"
SelectedValueBinding="{Binding Food}"
ItemsSourceBinding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.Foods}" />
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</DockPanel>
</TabItem>
<TabItem Header="DEVICES" TextElement.Foreground="{DynamicResource MaterialDesignBody}">
<DockPanel Margin="15">
<TextBlock DockPanel.Dock="Top">Below you view and manage the devices that were detected by Artemis</TextBlock>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="0 12 0 0">
<ItemsControl ItemsSource="{Binding DeviceSettingsViewModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl xaml:View.Model="{Binding}" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Top" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</TabItem>
</TabControl>
</UserControl> </UserControl>

View File

@ -1,4 +1,7 @@
using Artemis.Core.Services; using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.Services;
using Artemis.Core.Services.Storage.Interfaces; using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Settings.Debug; using Artemis.UI.Screens.Settings.Debug;
@ -34,10 +37,32 @@ namespace Artemis.UI.Screens.Settings
_deviceSettingsViewModelFactory = deviceSettingsViewModelFactory; _deviceSettingsViewModelFactory = deviceSettingsViewModelFactory;
DeviceSettingsViewModels = new BindableCollection<DeviceSettingsViewModel>(); DeviceSettingsViewModels = new BindableCollection<DeviceSettingsViewModel>();
RenderScales = new List<Tuple<string, double>> {new Tuple<string, double>("10%", 0.1)};
for (var i = 25; i <= 100; i += 25)
RenderScales.Add(new Tuple<string, double>(i + "%", i / 100.0));
TargetFrameRates = new List<Tuple<string, int>>();
for (var i = 10; i <= 30; i += 5)
TargetFrameRates.Add(new Tuple<string, int>(i + " FPS", i));
} }
public BindableCollection<DeviceSettingsViewModel> DeviceSettingsViewModels { get; set; } public BindableCollection<DeviceSettingsViewModel> DeviceSettingsViewModels { get; set; }
public List<Tuple<string, double>> RenderScales { get; set; }
public Tuple<string, double> SelectedRenderScale
{
get => RenderScales.FirstOrDefault(s => Math.Abs(s.Item2 - RenderScale) < 0.01);
set => RenderScale = value.Item2;
}
public Tuple<string, int> SelectedTargetFrameRate
{
get => TargetFrameRates.FirstOrDefault(t => Math.Abs(t.Item2 - TargetFrameRate) < 0.01);
set => TargetFrameRate = value.Item2;
}
public double RenderScale public double RenderScale
{ {
get => _settingsService.GetSetting("Core.RenderScale", 1.0).Value; get => _settingsService.GetSetting("Core.RenderScale", 1.0).Value;
@ -48,6 +73,8 @@ namespace Artemis.UI.Screens.Settings
} }
} }
public List<Tuple<string, int>> TargetFrameRates { get; set; }
public int TargetFrameRate public int TargetFrameRate
{ {
get => _settingsService.GetSetting("Core.TargetFrameRate", 25).Value; get => _settingsService.GetSetting("Core.TargetFrameRate", 25).Value;

View File

@ -20,7 +20,7 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Image Source="{StaticResource BowIcon}" Stretch="Uniform" Margin="6,50,6,6" /> <Image Source="{StaticResource BowIcon}" Stretch="Uniform" Margin="50" />
<TextBlock Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Foreground="White" FontSize="16"> <TextBlock Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Foreground="White" FontSize="16">
Artemis is initializing... Artemis is initializing...
</TextBlock> </TextBlock>