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

Core - Made FloatRange and IntRange readonly structs

ColorGradient - Fixed missing subscribtions when using object list manipulation API
ColorGradient - Fixed editor VM going out of sync
This commit is contained in:
Robert 2022-07-17 23:22:45 +02:00
parent bd26f447c6
commit e385165200
19 changed files with 337 additions and 327 deletions

View File

@ -1,83 +1,79 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<PreserveCompilationContext>false</PreserveCompilationContext>
<ShouldIncludeNativeSkiaSharp>false</ShouldIncludeNativeSkiaSharp>
<AssemblyTitle>Artemis.Core</AssemblyTitle>
<Product>Artemis Core</Product>
<Copyright>Copyright © Robert Beekman - 2020</Copyright>
<OutputPath>bin\</OutputPath>
<Platforms>x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DocumentationFile>bin\Artemis.Core.xml</DocumentationFile>
<NoWarn></NoWarn>
<WarningLevel>5</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<PreserveCompilationContext>false</PreserveCompilationContext>
<ShouldIncludeNativeSkiaSharp>false</ShouldIncludeNativeSkiaSharp>
<AssemblyTitle>Artemis.Core</AssemblyTitle>
<Product>Artemis Core</Product>
<Copyright>Copyright © Robert Beekman - 2020</Copyright>
<OutputPath>bin\</OutputPath>
<Platforms>x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DocumentationFile>bin\Artemis.Core.xml</DocumentationFile>
<NoWarn></NoWarn>
<WarningLevel>5</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<NrtRevisionFormat>1.0-{chash:6}</NrtRevisionFormat>
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
<NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute>
<NrtResolveCopyright>true</NrtResolveCopyright>
<NrtTagMatch>v[0-9]*</NrtTagMatch>
<NrtRemoveTagV>true</NrtRemoveTagV>
<NrtRequiredVcs>git</NrtRequiredVcs>
<NrtShowRevision>true</NrtShowRevision>
<Nullable>enable</Nullable>
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>
<PropertyGroup>
<NrtRevisionFormat>1.0-{chash:6}</NrtRevisionFormat>
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
<NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute>
<NrtResolveCopyright>true</NrtResolveCopyright>
<NrtTagMatch>v[0-9]*</NrtTagMatch>
<NrtRemoveTagV>true</NrtRemoveTagV>
<NrtRequiredVcs>git</NrtRequiredVcs>
<NrtShowRevision>true</NrtShowRevision>
<Nullable>enable</Nullable>
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DocumentationFile>bin\Artemis.Core.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj">
<Private>false</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="EmbedIO" Version="3.4.3" />
<PackageReference Include="HidSharp" Version="2.1.0" />
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="LiteDB" Version="5.0.11" />
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Ninject" Version="3.3.4" />
<PackageReference Include="Ninject.Extensions.ChildKernel" Version="3.3.0" />
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
<PackageReference Include="RGB.NET.Core" Version="1.0.0-prerelease.32" />
<PackageReference Include="RGB.NET.Layout" Version="1.0.0-prerelease.32" />
<PackageReference Include="RGB.NET.Presets" Version="1.0.0-prerelease.32" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Update="Resources\intro-profile.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DocumentationFile>bin\Artemis.Core.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj">
<Private>false</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="EmbedIO" Version="3.4.3"/>
<PackageReference Include="HidSharp" Version="2.1.0"/>
<PackageReference Include="Humanizer.Core" Version="2.14.1"/>
<PackageReference Include="LiteDB" Version="5.0.11"/>
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
<PackageReference Include="Ninject" Version="3.3.4"/>
<PackageReference Include="Ninject.Extensions.ChildKernel" Version="3.3.0"/>
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0"/>
<PackageReference Include="RGB.NET.Core" Version="1.0.0-prerelease.32"/>
<PackageReference Include="RGB.NET.Layout" Version="1.0.0-prerelease.32"/>
<PackageReference Include="RGB.NET.Presets" Version="1.0.0-prerelease.32"/>
<PackageReference Include="Serilog" Version="2.10.0"/>
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1"/>
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0"/>
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1"/>
<PackageReference Include="System.Buffers" Version="4.5.1"/>
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0"/>
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0"/>
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0"/>
<PackageReference Include="System.ValueTuple" Version="4.5.0"/>
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Update="Resources\intro-profile.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Update="DefaultLayouts\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="DefaultTypes\DataBindings\" />
</ItemGroup>
<ItemGroup>
<None Update="DefaultLayouts\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -1,91 +1,92 @@
using System.Collections.Specialized;
using System.ComponentModel;
using SkiaSharp;
namespace Artemis.Core
namespace Artemis.Core;
/// <inheritdoc />
public class ColorGradientLayerProperty : LayerProperty<ColorGradient>
{
/// <inheritdoc />
public class ColorGradientLayerProperty : LayerProperty<ColorGradient>
private ColorGradient? _subscribedGradient;
internal ColorGradientLayerProperty()
{
private ColorGradient? _subscribedGradient;
KeyframesSupported = false;
DefaultValue = new ColorGradient();
}
internal ColorGradientLayerProperty()
/// <summary>
/// Implicitly converts an <see cref="ColorGradientLayerProperty" /> to a <see cref="ColorGradient" />
/// </summary>
public static implicit operator ColorGradient(ColorGradientLayerProperty p)
{
return p.CurrentValue;
}
#region Overrides of LayerProperty<ColorGradient>
/// <inheritdoc />
protected override void OnCurrentValueSet()
{
// Don't allow color gradients to be null
if (BaseValue == null!)
BaseValue = new ColorGradient(DefaultValue);
if (!ReferenceEquals(_subscribedGradient, BaseValue))
{
KeyframesSupported = false;
DefaultValue = new ColorGradient();
CurrentValueSet += OnCurrentValueSet;
if (_subscribedGradient != null)
_subscribedGradient.CollectionChanged -= SubscribedGradientOnPropertyChanged;
_subscribedGradient = BaseValue;
_subscribedGradient.CollectionChanged += SubscribedGradientOnPropertyChanged;
}
private void CreateDataBindingRegistrations()
{
DataBinding.ClearDataBindingProperties();
if (CurrentValue == null!)
return;
CreateDataBindingRegistrations();
base.OnCurrentValueSet();
}
for (int index = 0; index < CurrentValue.Count; index++)
#endregion
/// <inheritdoc />
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
{
throw new ArtemisCoreException("Color Gradients do not support keyframes.");
}
#region Overrides of LayerProperty<ColorGradient>
/// <inheritdoc />
protected override void OnInitialize()
{
// Don't allow color gradients to be null
if (BaseValue == null!)
BaseValue = new ColorGradient(DefaultValue);
base.OnInitialize();
}
#endregion
private void CreateDataBindingRegistrations()
{
DataBinding.ClearDataBindingProperties();
if (CurrentValue == null!)
return;
for (int index = 0; index < CurrentValue.Count; index++)
{
int stopIndex = index;
void Setter(SKColor value)
{
int stopIndex = index;
void Setter(SKColor value)
{
CurrentValue[stopIndex].Color = value;
}
DataBinding.RegisterDataBindingProperty(() => CurrentValue[stopIndex].Color, Setter, $"Color #{stopIndex + 1}");
}
}
/// <summary>
/// Implicitly converts an <see cref="ColorGradientLayerProperty" /> to a <see cref="ColorGradient" />
/// </summary>
public static implicit operator ColorGradient(ColorGradientLayerProperty p)
{
return p.CurrentValue;
}
/// <inheritdoc />
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
{
throw new ArtemisCoreException("Color Gradients do not support keyframes.");
}
private void OnCurrentValueSet(object? sender, LayerPropertyEventArgs e)
{
// Don't allow color gradients to be null
if (BaseValue == null!)
BaseValue = new ColorGradient(DefaultValue);
if (!ReferenceEquals(_subscribedGradient, BaseValue))
{
if (_subscribedGradient != null)
_subscribedGradient.CollectionChanged -= SubscribedGradientOnPropertyChanged;
_subscribedGradient = BaseValue;
_subscribedGradient.CollectionChanged += SubscribedGradientOnPropertyChanged;
CurrentValue[stopIndex].Color = value;
}
DataBinding.RegisterDataBindingProperty(() => CurrentValue[stopIndex].Color, Setter, $"Color #{stopIndex + 1}");
}
}
private void SubscribedGradientOnPropertyChanged(object? sender, NotifyCollectionChangedEventArgs args)
{
if (CurrentValue.Count != DataBinding.Properties.Count)
CreateDataBindingRegistrations();
}
private void SubscribedGradientOnPropertyChanged(object? sender, NotifyCollectionChangedEventArgs args)
{
if (CurrentValue.Count != DataBinding.Properties.Count)
CreateDataBindingRegistrations();
}
#region Overrides of LayerProperty<ColorGradient>
/// <inheritdoc />
protected override void OnInitialize()
{
// Don't allow color gradients to be null
if (BaseValue == null!)
BaseValue = new ColorGradient(DefaultValue);
base.OnInitialize();
}
#endregion
}
}

View File

@ -3,17 +3,11 @@
/// <inheritdoc />
public class FloatRangeLayerProperty : LayerProperty<FloatRange>
{
internal FloatRangeLayerProperty()
{
CurrentValueSet += OnCurrentValueSet;
DefaultValue = new FloatRange();
}
/// <inheritdoc />
protected override void OnInitialize()
{
DataBinding.RegisterDataBindingProperty(() => CurrentValue.Start, value => CurrentValue.Start = value, "Start");
DataBinding.RegisterDataBindingProperty(() => CurrentValue.End, value => CurrentValue.End = value, "End");
DataBinding.RegisterDataBindingProperty(() => CurrentValue.Start, value => CurrentValue = new FloatRange(value, CurrentValue.End), "Start");
DataBinding.RegisterDataBindingProperty(() => CurrentValue.End, value => CurrentValue = new FloatRange(CurrentValue.Start, value), "End");
}
/// <inheritdoc />
@ -22,15 +16,9 @@
float startDiff = NextKeyframe!.Value.Start - CurrentKeyframe!.Value.Start;
float endDiff = NextKeyframe!.Value.End - CurrentKeyframe!.Value.End;
CurrentValue = new FloatRange(
(int) (CurrentKeyframe!.Value.Start + startDiff * keyframeProgressEased),
(int) (CurrentKeyframe!.Value.End + endDiff * keyframeProgressEased)
(float) (CurrentKeyframe!.Value.Start + startDiff * keyframeProgressEased),
(float) (CurrentKeyframe!.Value.End + endDiff * keyframeProgressEased)
);
}
private void OnCurrentValueSet(object? sender, LayerPropertyEventArgs e)
{
// Don't allow the int range to be null
BaseValue ??= DefaultValue ?? new FloatRange();
}
}
}

View File

@ -3,17 +3,11 @@
/// <inheritdoc />
public class IntRangeLayerProperty : LayerProperty<IntRange>
{
internal IntRangeLayerProperty()
{
CurrentValueSet += OnCurrentValueSet;
DefaultValue = new IntRange();
}
/// <inheritdoc />
protected override void OnInitialize()
{
DataBinding.RegisterDataBindingProperty(() => CurrentValue.Start, value => CurrentValue.Start = value, "Start");
DataBinding.RegisterDataBindingProperty(() => CurrentValue.End, value => CurrentValue.End = value, "End");
DataBinding.RegisterDataBindingProperty(() => CurrentValue.Start, value => CurrentValue = new IntRange(value, CurrentValue.End), "Start");
DataBinding.RegisterDataBindingProperty(() => CurrentValue.End, value => CurrentValue = new IntRange(CurrentValue.Start, value), "End");
}
/// <inheritdoc />
@ -26,11 +20,5 @@
(int) (CurrentKeyframe!.Value.End + endDiff * keyframeProgressEased)
);
}
private void OnCurrentValueSet(object? sender, LayerPropertyEventArgs e)
{
// Don't allow the int range to be null
BaseValue ??= DefaultValue ?? new IntRange();
}
}
}

View File

@ -55,6 +55,21 @@ public class ColorGradient : IList<ColorGradientStop>, IList, INotifyCollectionC
}
}
/// <summary>
/// Creates a new instance of the <see cref="ColorGradient" /> class
/// </summary>
/// <param name="stops">The stops to copy</param>
public ColorGradient(List<ColorGradientStop> stops)
{
_stops = new List<ColorGradientStop>();
foreach (ColorGradientStop colorGradientStop in stops)
{
ColorGradientStop stop = new(colorGradientStop.Color, colorGradientStop.Position);
stop.PropertyChanged += ItemOnPropertyChanged;
_stops.Add(stop);
}
}
/// <summary>
/// Gets all the colors in the color gradient
/// </summary>
@ -462,7 +477,7 @@ public class ColorGradient : IList<ColorGradientStop>, IList, INotifyCollectionC
public int Add(object? value)
{
if (value is ColorGradientStop stop)
_stops.Add(stop);
Add(stop);
return IndexOf(value);
}
@ -492,14 +507,14 @@ public class ColorGradient : IList<ColorGradientStop>, IList, INotifyCollectionC
public void Insert(int index, object? value)
{
if (value is ColorGradientStop stop)
_stops.Insert(index, stop);
Insert(index, stop);
}
/// <inheritdoc />
public void Remove(object? value)
{
if (value is ColorGradientStop stop)
_stops.Remove(stop);
Remove(stop);
}
/// <inheritdoc />

View File

@ -633,6 +633,7 @@ namespace Artemis.Core
if (!baseLayerEffect.Suspended)
baseLayerEffect.InternalPreProcess(canvas, bounds, layerPaint);
}
canvas.ClipPath(renderPath);
// Restore the blend mode before doing the actual render
@ -788,10 +789,14 @@ namespace Artemis.Core
/// </summary>
public void ChangeLayerBrush(BaseLayerBrush? layerBrush)
{
BaseLayerBrush? oldLayerBrush = LayerBrush;
General.BrushReference.SetCurrentValue(layerBrush != null ? new LayerBrushReference(layerBrush.Descriptor) : null, null);
LayerBrush = layerBrush;
LayerEntity.LayerBrush = new LayerBrushEntity();
oldLayerBrush?.InternalDisable();
if (LayerBrush != null)
ActivateLayerBrush();
else
@ -815,7 +820,12 @@ namespace Artemis.Core
General.ShapeType.IsHidden = LayerBrush != null && !LayerBrush.SupportsTransformation;
General.BlendMode.IsHidden = LayerBrush != null && !LayerBrush.SupportsTransformation;
Transform.IsHidden = LayerBrush != null && !LayerBrush.SupportsTransformation;
LayerBrush?.Update(0);
if (LayerBrush != null)
{
if (!LayerBrush.Enabled)
LayerBrush.InternalEnable();
LayerBrush?.Update(0);
}
OnLayerBrushUpdated();
ClearBrokenState("Failed to initialize layer brush");

View File

@ -5,18 +5,10 @@ namespace Artemis.Core
/// <summary>
/// Represents a range between two single-precision floating point numbers
/// </summary>
public class FloatRange
public readonly struct FloatRange
{
private readonly Random _rand;
/// <summary>
/// Creates a new instance of the <see cref="FloatRange" /> class
/// </summary>
public FloatRange()
{
_rand = new Random();
}
/// <summary>
/// Creates a new instance of the <see cref="FloatRange" /> class
/// </summary>
@ -31,14 +23,14 @@ namespace Artemis.Core
}
/// <summary>
/// Gets or sets the start value of the range
/// Gets the start value of the range
/// </summary>
public float Start { get; set; }
public float Start { get; }
/// <summary>
/// Gets or sets the end value of the range
/// Gets the end value of the range
/// </summary>
public float End { get; set; }
public float End { get; }
/// <summary>
/// Determines whether the given value is in this range

View File

@ -5,18 +5,10 @@ namespace Artemis.Core
/// <summary>
/// Represents a range between two signed integers
/// </summary>
public class IntRange
public readonly struct IntRange
{
private readonly Random _rand;
/// <summary>
/// Creates a new instance of the <see cref="IntRange" /> class
/// </summary>
public IntRange()
{
_rand = new Random();
}
/// <summary>
/// Creates a new instance of the <see cref="IntRange" /> class
/// </summary>
@ -31,14 +23,14 @@ namespace Artemis.Core
}
/// <summary>
/// Gets or sets the start value of the range
/// Gets the start value of the range
/// </summary>
public int Start { get; set; }
public int Start { get; }
/// <summary>
/// Gets or sets the end value of the range
/// Gets the end value of the range
/// </summary>
public int End { get; set; }
public int End { get; }
/// <summary>
/// Determines whether the given value is in this range

View File

@ -261,7 +261,7 @@ namespace Artemis.Core
/// <summary>
/// Gets whether keyframes are supported on this type of property
/// </summary>
public bool KeyframesSupported { get; protected internal set; } = true;
public bool KeyframesSupported { get; protected set; } = true;
/// <summary>
/// Gets or sets whether keyframes are enabled on this property, has no effect if <see cref="KeyframesSupported" /> is

View File

@ -39,8 +39,6 @@ namespace Artemis.Core.LayerBrushes
PropertyGroupDescriptionAttribute groupDescription = new() {Identifier = "Brush", Name = Descriptor.DisplayName, Description = Descriptor.Description};
Properties.Initialize(Layer, null, groupDescription, propertyGroupEntity);
PropertiesInitialized = true;
EnableLayerBrush();
}
}
}

View File

@ -3,8 +3,8 @@
<OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ApplicationIcon />
<StartupObject />
<ApplicationIcon/>
<StartupObject/>
<OutputPath>bin\</OutputPath>
<PlatformTarget>x64</PlatformTarget>
<Platforms>x64</Platforms>
@ -15,20 +15,20 @@
<ItemGroup>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.15" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.15" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.15" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.14" />
<PackageReference Include="DynamicData" Version="7.8.6" />
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1" />
<PackageReference Include="Material.Icons.Avalonia" Version="1.0.2" />
<PackageReference Include="ReactiveUI" Version="17.1.50" />
<PackageReference Include="ReactiveUI.Validation" Version="2.2.1" />
<PackageReference Include="RGB.NET.Core" Version="1.0.0-prerelease.32" />
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1" />
<PackageReference Include="Avalonia" Version="0.10.15"/>
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.15"/>
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.15"/>
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.14"/>
<PackageReference Include="DynamicData" Version="7.8.6"/>
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1"/>
<PackageReference Include="Material.Icons.Avalonia" Version="1.0.2"/>
<PackageReference Include="ReactiveUI" Version="17.1.50"/>
<PackageReference Include="ReactiveUI.Validation" Version="2.2.1"/>
<PackageReference Include="RGB.NET.Core" Version="1.0.0-prerelease.32"/>
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj"/>
</ItemGroup>
<ItemGroup>
<Compile Update="Controls\HotkeyBox.axaml.cs">

View File

@ -24,7 +24,7 @@ public class GradientPickerButton : TemplatedControl
/// Gets or sets the color gradient.
/// </summary>
public static readonly StyledProperty<ColorGradient?> ColorGradientProperty =
AvaloniaProperty.Register<GradientPickerButton, ColorGradient?>(nameof(ColorGradient), notifying: ColorGradientChanged, defaultValue: ColorGradient.GetUnicornBarf());
AvaloniaProperty.Register<GradientPickerButton, ColorGradient?>(nameof(ColorGradient), notifying: ColorGradientChanged);
/// <summary>
/// Gets or sets a boolean indicating whether the gradient picker should be in compact mode or not.
@ -108,7 +108,8 @@ public class GradientPickerButton : TemplatedControl
private static void ColorGradientChanged(IAvaloniaObject sender, bool before)
{
(sender as GradientPickerButton)?.Subscribe();
if (!before)
(sender as GradientPickerButton)?.Subscribe();
}
private void Subscribe()

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core;
namespace Artemis.UI.Shared.Services.ProfileEditor.Commands;
/// <summary>
/// Represents a profile editor command that can be used to update a layer property of type <typeparamref name="T" />.
/// </summary>
public class UpdateColorGradient : IProfileEditorCommand
{
private readonly ColorGradient _colorGradient;
private readonly List<ColorGradientStop> _stops;
private readonly List<ColorGradientStop> _originalStops;
/// <summary>
/// Creates a new instance of the <see cref="UpdateColorGradient" /> class.
/// </summary>
public UpdateColorGradient(ColorGradient colorGradient, List<ColorGradientStop> stops, List<ColorGradientStop>? originalStops)
{
_colorGradient = colorGradient;
_stops = stops;
_originalStops = originalStops ?? _colorGradient.Select(s => new ColorGradientStop(s.Color, s.Position)).ToList();
}
#region Implementation of IProfileEditorCommand
/// <inheritdoc />
public string DisplayName => "Update color gradient";
/// <inheritdoc />
public void Execute()
{
_colorGradient.Clear();
foreach (ColorGradientStop colorGradientStop in _stops)
_colorGradient.Add(colorGradientStop);
}
/// <inheritdoc />
public void Undo()
{
_colorGradient.Clear();
foreach (ColorGradientStop colorGradientStop in _originalStops)
_colorGradient.Add(colorGradientStop);
}
#endregion
}

View File

@ -8,44 +8,44 @@
<Platforms>x64</Platforms>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
<AvaloniaResource Include="Assets\**"/>
</ItemGroup>
<ItemGroup>
<None Remove="Artemis.UI.Avalonia.csproj.DotSettings" />
<None Remove="Artemis.UI.csproj.DotSettings" />
<None Remove="Assets\Images\Logo\application.ico" />
<None Remove="Artemis.UI.Avalonia.csproj.DotSettings"/>
<None Remove="Artemis.UI.csproj.DotSettings"/>
<None Remove="Assets\Images\Logo\application.ico"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.15" />
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="10.14.0" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.15" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.15" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.15" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.14" />
<PackageReference Include="DynamicData" Version="7.8.6" />
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1" />
<PackageReference Include="Flurl.Http" Version="3.2.4" />
<PackageReference Include="Live.Avalonia" Version="1.3.1" />
<PackageReference Include="Material.Icons.Avalonia" Version="1.0.2" />
<PackageReference Include="ReactiveUI" Version="17.1.50" />
<PackageReference Include="ReactiveUI.Validation" Version="2.2.1" />
<PackageReference Include="RGB.NET.Core" Version="1.0.0-prerelease.32" />
<PackageReference Include="RGB.NET.Layout" Version="1.0.0-prerelease.32" />
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1" />
<PackageReference Include="Splat.Ninject" Version="14.1.45" />
<PackageReference Include="Avalonia" Version="0.10.15"/>
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="10.14.0"/>
<PackageReference Include="Avalonia.Desktop" Version="0.10.15"/>
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.15"/>
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.15"/>
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.14"/>
<PackageReference Include="DynamicData" Version="7.8.6"/>
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1"/>
<PackageReference Include="Flurl.Http" Version="3.2.4"/>
<PackageReference Include="Live.Avalonia" Version="1.3.1"/>
<PackageReference Include="Material.Icons.Avalonia" Version="1.0.2"/>
<PackageReference Include="ReactiveUI" Version="17.1.50"/>
<PackageReference Include="ReactiveUI.Validation" Version="2.2.1"/>
<PackageReference Include="RGB.NET.Core" Version="1.0.0-prerelease.32"/>
<PackageReference Include="RGB.NET.Layout" Version="1.0.0-prerelease.32"/>
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1"/>
<PackageReference Include="Splat.Ninject" Version="14.1.45"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj" />
<ProjectReference Include="..\Artemis.VisualScripting\Artemis.VisualScripting.csproj" />
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj"/>
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj"/>
<ProjectReference Include="..\Artemis.VisualScripting\Artemis.VisualScripting.csproj"/>
</ItemGroup>
<ItemGroup>
<Content Include="Assets\Images\Logo\bow-white.ico" />
<Content Include="Assets\Images\Logo\bow.ico" />
<Content Include="Assets\Images\Logo\bow-white.ico"/>
<Content Include="Assets\Images\Logo\bow.ico"/>
</ItemGroup>
<ItemGroup>
<Resource Include="Assets\Images\Logo\bow-black.ico" />
<Resource Include="Assets\Images\Logo\bow-white.ico" />
<Resource Include="Assets\Images\Logo\bow-black.ico"/>
<Resource Include="Assets\Images\Logo\bow-white.ico"/>
</ItemGroup>
<ItemGroup>
<Compile Update="DefaultTypes\PropertyInput\StringPropertyInputView.axaml.cs">
@ -72,8 +72,8 @@
<SubType>Code</SubType>
</Compile>
<Compile Update="Screens\Scripting\Dialogs\ScriptConfigurationEditView.axaml.cs">
<DependentUpon>ScriptConfigurationEditView.axaml</DependentUpon>
<SubType>Code</SubType>
<DependentUpon>ScriptConfigurationEditView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>

View File

@ -9,7 +9,7 @@
x:DataType="propertyInput:ColorGradientPropertyInputViewModel">
<gradientPicker:GradientPickerButton Classes="condensed"
Width="200"
ColorGradient="{CompiledBinding ColorGradient}"
ColorGradient="{CompiledBinding InputValue}"
VerticalAlignment="Center"
FlyoutOpened="GradientPickerButton_OnFlyoutOpened"
FlyoutClosed="GradientPickerButton_OnFlyoutClosed"/>

View File

@ -1,4 +1,6 @@
using Artemis.Core;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core;
using Artemis.UI.Shared.Services.ProfileEditor;
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
using Artemis.UI.Shared.Services.PropertyInput;
@ -9,37 +11,19 @@ namespace Artemis.UI.DefaultTypes.PropertyInput;
public class ColorGradientPropertyInputViewModel : PropertyInputViewModel<ColorGradient>
{
private ColorGradient _colorGradient = null!;
private ColorGradient? _originalGradient;
private List<ColorGradientStop>? _originalStops;
public ColorGradientPropertyInputViewModel(LayerProperty<ColorGradient> layerProperty, IProfileEditorService profileEditorService, IPropertyInputService propertyInputService)
: base(layerProperty, profileEditorService, propertyInputService)
{
}
public ColorGradient ColorGradient
{
get => _colorGradient;
set => this.RaiseAndSetIfChanged(ref _colorGradient, value);
}
protected override void OnInputValueChanged()
{
ColorGradient = new ColorGradient(InputValue);
}
#region Overrides of PropertyInputViewModel<ColorGradient>
/// <inheritdoc />
public override void StartPreview()
{
_originalGradient = LayerProperty.CurrentValue;
// Set the property value to the gradient being edited by the picker, this will cause any updates to show right away because
// ColorGradient is a reference type
LayerProperty.CurrentValue = ColorGradient;
// This won't fly if we ever support keyframes but at that point ColorGradient would have to be a value type anyway and this
// whole VM no longer makes sense
_originalStops = InputValue?.Select(s => new ColorGradientStop(s.Color, s.Position)).ToList();
}
/// <inheritdoc />
@ -51,28 +35,40 @@ public class ColorGradientPropertyInputViewModel : PropertyInputViewModel<ColorG
/// <inheritdoc />
public override void ApplyPreview()
{
if (_originalGradient == null)
// If the new stops are equal to the old ones, nothing changes
if (InputValue == null || _originalStops == null || !HasPreviewChanges())
return;
// Make sure something actually changed
if (Equals(ColorGradient, _originalGradient))
LayerProperty.CurrentValue = _originalGradient;
else
// Update the gradient for realsies, giving the command a reference to the old gradient
ProfileEditorService.ExecuteCommand(new UpdateLayerProperty<ColorGradient>(LayerProperty, ColorGradient, _originalGradient, Time));
_originalGradient = null;
ProfileEditorService.ExecuteCommand(new UpdateColorGradient(InputValue, InputValue.ToList(), _originalStops));
_originalStops = null;
}
/// <inheritdoc />
public override void DiscardPreview()
{
if (_originalGradient == null)
if (InputValue == null || _originalStops == null)
return;
// Put the old gradient back
InputValue = _originalGradient;
ColorGradient = new ColorGradient(InputValue);
InputValue.Clear();
foreach (ColorGradientStop colorGradientStop in _originalStops)
InputValue.Add(colorGradientStop);
_originalStops = null;
}
private bool HasPreviewChanges()
{
if (InputValue == null || _originalStops == null)
return false;
if (InputValue.Count != _originalStops.Count)
return true;
for (int i = 0; i < InputValue.Count; i++)
if (!Equals(InputValue[i], _originalStops[i]))
return true;
return false;
}
#endregion

View File

@ -30,28 +30,20 @@ public class FloatRangePropertyInputViewModel : PropertyInputViewModel<FloatRang
public float Start
{
get => InputValue?.Start ?? 0;
get => InputValue.Start;
set
{
if (InputValue == null)
InputValue = new FloatRange(value, value + 1);
else
InputValue.Start = value;
InputValue = new FloatRange(value, InputValue.End);
this.RaisePropertyChanged(nameof(Start));
}
}
public float End
{
get => InputValue?.End ?? 0;
get => InputValue.End;
set
{
if (InputValue == null)
InputValue = new FloatRange(value - 1, value);
else
InputValue.End = value;
InputValue = new FloatRange(InputValue.Start, value);
this.RaisePropertyChanged(nameof(End));
}
}

View File

@ -30,28 +30,20 @@ public class IntRangePropertyInputViewModel : PropertyInputViewModel<IntRange>
public int Start
{
get => InputValue?.Start ?? 0;
get => InputValue.Start;
set
{
if (InputValue == null)
InputValue = new IntRange(value, value + 1);
else
InputValue.Start = value;
InputValue = new IntRange(value, InputValue.End);
this.RaisePropertyChanged(nameof(Start));
}
}
public int End
{
get => InputValue?.End ?? 0;
get => InputValue.End;
set
{
if (InputValue == null)
InputValue = new IntRange(value - 1, value);
else
InputValue.End = value;
InputValue = new IntRange(InputValue.Start, value);
this.RaisePropertyChanged(nameof(End));
}
}