1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-02-04 10:53:31 +00:00

Merge branch 'development'

This commit is contained in:
Robert 2023-06-11 22:51:15 +02:00
commit f5688db630
23 changed files with 196 additions and 200 deletions

View File

@ -43,9 +43,9 @@
<PackageReference Include="LiteDB" Version="5.0.16" /> <PackageReference Include="LiteDB" Version="5.0.16" />
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0" /> <PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.69" /> <PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.76" />
<PackageReference Include="RGB.NET.Layout" Version="2.0.0-prerelease.69" /> <PackageReference Include="RGB.NET.Layout" Version="2.0.0-prerelease.76" />
<PackageReference Include="RGB.NET.Presets" Version="2.0.0-prerelease.69" /> <PackageReference Include="RGB.NET.Presets" Version="2.0.0-prerelease.76" />
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" /> <PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />

View File

@ -16,11 +16,11 @@
<None Remove=".gitignore" /> <None Remove=".gitignore" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
<PackageReference Include="ReactiveUI" Version="18.4.26" /> <PackageReference Include="ReactiveUI" Version="18.4.26" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -15,11 +15,11 @@
<None Remove=".gitignore" /> <None Remove=".gitignore" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
<PackageReference Include="ReactiveUI" Version="18.4.26" /> <PackageReference Include="ReactiveUI" Version="18.4.26" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -10,17 +10,17 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-rc1.1" />
<PackageReference Include="DynamicData" Version="7.13.1" /> <PackageReference Include="DynamicData" Version="7.13.1" />
<PackageReference Include="FluentAvaloniaUI" Version="2.0.0-preview8" /> <PackageReference Include="FluentAvaloniaUI" Version="2.0.0-rc1" />
<PackageReference Include="Material.Icons.Avalonia" Version="2.0.0-preview3" /> <PackageReference Include="Material.Icons.Avalonia" Version="2.0.1" />
<PackageReference Include="ReactiveUI" Version="18.4.26" /> <PackageReference Include="ReactiveUI" Version="18.4.26" />
<PackageReference Include="ReactiveUI.Validation" Version="3.1.7" /> <PackageReference Include="ReactiveUI.Validation" Version="3.1.7" />
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.69" /> <PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.76" />
<PackageReference Include="SkiaSharp" Version="2.88.3" /> <PackageReference Include="SkiaSharp" Version="2.88.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -6,25 +6,27 @@
xmlns:sharedControls="clr-namespace:Artemis.UI.Shared.Controls" xmlns:sharedControls="clr-namespace:Artemis.UI.Shared.Controls"
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties" xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Shared.Controls.DraggableNumberBox"> x:Class="Artemis.UI.Shared.Controls.DraggableNumberBox"
Focusable="True">
<UserControl.Styles> <UserControl.Styles>
<Styles> <Styles>
<Style Selector="sharedControls|DraggableNumberBox:not(:focus-within)"> <Style Selector="Panel#Container:not(:focus-within)">
<Setter Property="Cursor" Value="{DynamicResource DragHorizontalCursor}" /> <Setter Property="Cursor" Value="{DynamicResource DragHorizontalCursor}" />
</Style> </Style>
<Style Selector="sharedControls|DraggableNumberBox:focus-within Rectangle#DragCollider"> <Style Selector="#Container:focus-within Rectangle#DragCollider">
<Setter Property="IsHitTestVisible" Value="False" /> <Setter Property="IsHitTestVisible" Value="False" />
</Style> </Style>
<Style Selector="sharedControls|DraggableNumberBox:not(:focus-within) controls|NumberBox#NumberBox"> <Style Selector="#Container:not(:focus-within) controls|NumberBox#NumberBox">
<Setter Property="IsHitTestVisible" Value="False" /> <Setter Property="IsHitTestVisible" Value="False" />
</Style> </Style>
</Styles> </Styles>
</UserControl.Styles> </UserControl.Styles>
<Panel> <Panel Name="Container" Focusable="True">
<controls:NumberBox Name="InnerNumberBox" <controls:NumberBox Name="InnerNumberBox"
AcceptsExpression="True" AcceptsExpression="True"
Focusable="True"
LargeChange="{CompiledBinding $parent[sharedControls:DraggableNumberBox].LargeChange}" LargeChange="{CompiledBinding $parent[sharedControls:DraggableNumberBox].LargeChange}"
SmallChange="{CompiledBinding $parent[sharedControls:DraggableNumberBox].SmallChange}" SmallChange="{CompiledBinding $parent[sharedControls:DraggableNumberBox].SmallChange}"
Minimum="{CompiledBinding $parent[sharedControls:DraggableNumberBox].Minimum}" Minimum="{CompiledBinding $parent[sharedControls:DraggableNumberBox].Minimum}"

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Linq;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Data; using Avalonia.Data;
@ -186,8 +187,8 @@ public partial class DraggableNumberBox : UserControl
private void HandleKeyUp(object? sender, KeyEventArgs e) private void HandleKeyUp(object? sender, KeyEventArgs e)
{ {
if (e.Key == Key.Enter || e.Key == Key.Escape) if (e.Key is Key.Enter or Key.Escape)
FocusManager.Instance?.Focus(Parent as IInputElement); Focus();
} }
private void OnPointerPressed(object? sender, PointerPressedEventArgs e) private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
@ -215,9 +216,9 @@ public partial class DraggableNumberBox : UserControl
if (!_moved) if (!_moved)
{ {
// Let our parent take focus, it would make more sense to take focus ourselves but that hides the collider // Let our parent take focus, it would make more sense to take focus ourselves but that hides the collider
FocusManager.Instance?.Focus(Parent as IInputElement); PseudoClasses.Add("dragging");
Focus();
_moved = true; _moved = true;
e.Pointer.Capture(this);
DragStarted?.Invoke(this, EventArgs.Empty); DragStarted?.Invoke(this, EventArgs.Empty);
} }
@ -252,6 +253,7 @@ public partial class DraggableNumberBox : UserControl
else else
{ {
_moved = false; _moved = false;
PseudoClasses.Remove("dragging");
DragFinished?.Invoke(this, EventArgs.Empty); DragFinished?.Invoke(this, EventArgs.Empty);
} }

View File

@ -9,6 +9,7 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Threading; using Avalonia.Threading;
using Avalonia.VisualTree;
using DryIoc; using DryIoc;
using FluentAvalonia.Core; using FluentAvalonia.Core;
using Humanizer; using Humanizer;
@ -78,7 +79,19 @@ public partial class HotkeyBox : UserControl
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e) private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
{ {
if (e.Modifiers == KeyboardModifierKey.None) if (e.Modifiers == KeyboardModifierKey.None)
Dispatcher.UIThread.Post(() => FocusManager.Instance?.Focus(null)); Dispatcher.UIThread.Post(ClearFocus);
}
private void ClearFocus()
{
InputElement? element = this.FindAncestorOfType<InputElement>();
if (element == null)
return;
bool wasFocusable = element.Focusable;
element.Focusable = true;
element.Focus();
element.Focusable = wasFocusable;
} }
private void UpdateDisplayTextBox() private void UpdateDisplayTextBox()
@ -96,7 +109,7 @@ public partial class HotkeyBox : UserControl
private void Button_OnClick(object? sender, RoutedEventArgs e) private void Button_OnClick(object? sender, RoutedEventArgs e)
{ {
Hotkey = null; Hotkey = null;
FocusManager.Instance?.Focus(null); ClearFocus();
UpdateDisplayTextBox(); UpdateDisplayTextBox();
} }

View File

@ -48,7 +48,7 @@ public class ReactiveAppWindow<TViewModel> : AppWindow, IViewFor<TViewModel> whe
return; return;
TransparencyBackgroundFallback = Brushes.Transparent; TransparencyBackgroundFallback = Brushes.Transparent;
TransparencyLevelHint = WindowTransparencyLevel.Mica; TransparencyLevelHint = new[] {WindowTransparencyLevel.Mica};
TryEnableMicaEffect(); TryEnableMicaEffect();
} }

View File

@ -77,6 +77,6 @@ public class SaveFileDialogBuilder
public async Task<string?> ShowAsync() public async Task<string?> ShowAsync()
{ {
IStorageFile? path = await _parent.StorageProvider.SaveFilePickerAsync(_options); IStorageFile? path = await _parent.StorageProvider.SaveFilePickerAsync(_options);
return path?.Path.AbsolutePath; return path?.Path.LocalPath;
} }
} }

View File

@ -3,27 +3,30 @@
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties" xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties"
xmlns:system="clr-namespace:System;assembly=System.Runtime"> xmlns:system="clr-namespace:System;assembly=System.Runtime">
<Design.PreviewWith> <Design.PreviewWith>
<Border Padding="20"> <Border Padding="20">
<StackPanel Spacing="20"> <StackPanel Spacing="20">
<!-- Add Controls for Previewer Here --> <!-- Add Controls for Previewer Here -->
<controls:NumberBox Value="99999999" <controls:NumberBox Value="99999999"
attachedProperties:NumberBoxAssist.PrefixText="%" attachedProperties:NumberBoxAssist.PrefixText="%"
attachedProperties:NumberBoxAssist.SuffixText="%"/> attachedProperties:NumberBoxAssist.SuffixText="%" />
<controls:NumberBox Classes="condensed" <controls:NumberBox Classes="condensed"
Value="9999999" Value="9999999"
attachedProperties:NumberBoxAssist.PrefixText="%" attachedProperties:NumberBoxAssist.PrefixText="%"
attachedProperties:NumberBoxAssist.SuffixText="%"> attachedProperties:NumberBoxAssist.SuffixText="%">
<DataValidationErrors.Error> <DataValidationErrors.Error>
<system:Exception/> <system:Exception />
</DataValidationErrors.Error> </DataValidationErrors.Error>
</controls:NumberBox> </controls:NumberBox>
</StackPanel> </StackPanel>
</Border> </Border>
</Design.PreviewWith> </Design.PreviewWith>
<!-- Add Styles Here --> <Style Selector="controls|NumberBox">
<Setter Property="Maximum" Value="{x:Static system:Double.MaxValue}"></Setter>
<Setter Property="Minimum" Value="{x:Static system:Double.MinValue}"></Setter>
</Style>
<Style Selector="controls|NumberBox /template/ TextBox.NumberBoxTextBoxStyle /template/ TextBlock#PART_Prefix"> <Style Selector="controls|NumberBox /template/ TextBox.NumberBoxTextBoxStyle /template/ TextBlock#PART_Prefix">
<Setter Property="Foreground" Value="{DynamicResource TextControlForegroundDisabled}"></Setter> <Setter Property="Foreground" Value="{DynamicResource TextControlForegroundDisabled}"></Setter>
<Setter Property="Margin" Value="-4 0 -12 0"></Setter> <Setter Property="Margin" Value="-4 0 -12 0"></Setter>
@ -39,9 +42,7 @@
<Style Selector="controls|NumberBox.condensed /template/ TextBox.NumberBoxTextBoxStyle /template/ TextBlock#PART_Suffix"> <Style Selector="controls|NumberBox.condensed /template/ TextBox.NumberBoxTextBoxStyle /template/ TextBlock#PART_Suffix">
<Setter Property="Margin" Value="-4 0 0 0"></Setter> <Setter Property="Margin" Value="-4 0 0 0"></Setter>
</Style> </Style>
<Style Selector="controls|NumberBox /template/ TextBox.NumberBoxTextBoxStyle">
<Style Selector="controls|NumberBox /template/ TextBox.NumberBoxTextBoxStyle">
<Setter Property="attachedProperties:TextBoxAssist.PrefixText" Value="{TemplateBinding attachedProperties:NumberBoxAssist.PrefixText}"></Setter> <Setter Property="attachedProperties:TextBoxAssist.PrefixText" Value="{TemplateBinding attachedProperties:NumberBoxAssist.PrefixText}"></Setter>
<Setter Property="attachedProperties:TextBoxAssist.SuffixText" Value="{TemplateBinding attachedProperties:NumberBoxAssist.SuffixText}"></Setter> <Setter Property="attachedProperties:TextBoxAssist.SuffixText" Value="{TemplateBinding attachedProperties:NumberBoxAssist.SuffixText}"></Setter>
</Style> </Style>

View File

@ -1,7 +1,5 @@
using System; using System;
using System.ComponentModel;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Subjects;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Platform; using Avalonia.Input.Platform;
@ -14,12 +12,9 @@ namespace Artemis.UI.Shared;
/// </summary> /// </summary>
public static class UI public static class UI
{ {
private static readonly BehaviorSubject<bool> KeyBindingsEnabledSubject = new(false);
static UI() static UI()
{ {
if (KeyboardDevice.Instance != null) KeyBindingsEnabled = InputElement.GotFocusEvent.Raised.Select(e => e.Item2.Source is not TextBox).StartWith(true);
KeyboardDevice.Instance.PropertyChanged += InstanceOnPropertyChanged;
} }
/// <summary> /// <summary>
@ -35,15 +30,5 @@ public static class UI
/// <summary> /// <summary>
/// Gets a boolean indicating whether hotkeys are to be disabled. /// Gets a boolean indicating whether hotkeys are to be disabled.
/// </summary> /// </summary>
public static IObservable<bool> KeyBindingsEnabled { get; } = KeyBindingsEnabledSubject.AsObservable(); public static IObservable<bool> KeyBindingsEnabled { get; }
private static void InstanceOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (KeyboardDevice.Instance == null || e.PropertyName != nameof(KeyboardDevice.FocusedElement))
return;
bool enabled = KeyboardDevice.Instance.FocusedElement is not TextBox;
if (KeyBindingsEnabledSubject.Value != enabled)
KeyBindingsEnabledSubject.OnNext(enabled);
}
} }

View File

@ -21,12 +21,12 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Win32" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Win32" Version="11.0.0-rc1.1" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" /> <PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
<PackageReference Include="Microsoft.Win32" Version="2.0.1" /> <PackageReference Include="Microsoft.Win32" Version="2.0.1" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="7.0.0" /> <PackageReference Include="Microsoft.Windows.Compatibility" Version="7.0.0" />

View File

@ -490,6 +490,19 @@ public static class InputUtilities
88 => KeyboardKey.F12, 88 => KeyboardKey.F12,
91 => KeyboardKey.LeftWin, 91 => KeyboardKey.LeftWin,
92 => KeyboardKey.RightWin, 92 => KeyboardKey.RightWin,
100 => KeyboardKey.F13,
101 => KeyboardKey.F14,
102 => KeyboardKey.F15,
103 => KeyboardKey.F16,
104 => KeyboardKey.F17,
105 => KeyboardKey.F18,
106 => KeyboardKey.F19,
107 => KeyboardKey.F20,
108 => KeyboardKey.F21,
109 => KeyboardKey.F22,
110 => KeyboardKey.F23,
//???
118 => KeyboardKey.F24,
//28 = enter or numpad enter //28 = enter or numpad enter
//29 = left ctrl or right ctrl //29 = left ctrl or right ctrl

View File

@ -15,25 +15,25 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-rc1.1" />
<PackageReference Include="DryIoc.dll" Version="5.4.0" /> <PackageReference Include="DryIoc.dll" Version="5.4.0" />
<PackageReference Include="DynamicData" Version="7.13.1" /> <PackageReference Include="DynamicData" Version="7.13.1" />
<PackageReference Include="FluentAvaloniaUI" Version="2.0.0-preview8" /> <PackageReference Include="FluentAvaloniaUI" Version="2.0.0-rc1" />
<PackageReference Include="Flurl.Http" Version="3.2.4" /> <PackageReference Include="Flurl.Http" Version="3.2.4" />
<PackageReference Include="Live.Avalonia" Version="1.3.1" /> <PackageReference Include="Live.Avalonia" Version="1.3.1" />
<PackageReference Include="Markdown.Avalonia.Tight" Version="11.0.0-c1" /> <PackageReference Include="Markdown.Avalonia.Tight" Version="11.0.0-d1" />
<PackageReference Include="Material.Icons.Avalonia" Version="2.0.0-preview3" /> <PackageReference Include="Material.Icons.Avalonia" Version="2.0.1" />
<PackageReference Include="Octopus.Octodiff" Version="2.0.261" /> <PackageReference Include="Octopus.Octodiff" Version="2.0.261" />
<PackageReference Include="ReactiveUI" Version="18.4.26" /> <PackageReference Include="ReactiveUI" Version="18.4.26" />
<PackageReference Include="ReactiveUI.Validation" Version="3.1.7" /> <PackageReference Include="ReactiveUI.Validation" Version="3.1.7" />
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.69" /> <PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.76" />
<PackageReference Include="RGB.NET.Layout" Version="2.0.0-prerelease.69" /> <PackageReference Include="RGB.NET.Layout" Version="2.0.0-prerelease.76" />
<PackageReference Include="SkiaSharp" Version="2.88.3" /> <PackageReference Include="SkiaSharp" Version="2.88.3" />
<PackageReference Include="Splat.DryIoc" Version="14.6.8" /> <PackageReference Include="Splat.DryIoc" Version="14.6.8" />
</ItemGroup> </ItemGroup>

View File

@ -103,8 +103,9 @@ public class SimpleContextDragBehavior : Behavior<Control>
private void AssociatedObject_PointerPressed(object? sender, PointerPressedEventArgs e) private void AssociatedObject_PointerPressed(object? sender, PointerPressedEventArgs e)
{ {
IFocusManager? focusManager = TopLevel.GetTopLevel(AssociatedObject)?.FocusManager;
PointerPointProperties properties = e.GetCurrentPoint(AssociatedObject).Properties; PointerPointProperties properties = e.GetCurrentPoint(AssociatedObject).Properties;
if (!properties.IsLeftButtonPressed || FocusManager.Instance?.Current is TextBox) if (!properties.IsLeftButtonPressed || focusManager?.GetFocusedElement() is TextBox)
return; return;
if (e.Source is not Control control || AssociatedObject?.DataContext != control.DataContext) if (e.Source is not Control control || AssociatedObject?.DataContext != control.DataContext)
return; return;
@ -130,8 +131,9 @@ public class SimpleContextDragBehavior : Behavior<Control>
private async void AssociatedObject_PointerMoved(object? sender, PointerEventArgs e) private async void AssociatedObject_PointerMoved(object? sender, PointerEventArgs e)
{ {
IFocusManager? focusManager = TopLevel.GetTopLevel(AssociatedObject)?.FocusManager;
PointerPointProperties properties = e.GetCurrentPoint(AssociatedObject).Properties; PointerPointProperties properties = e.GetCurrentPoint(AssociatedObject).Properties;
if (!properties.IsLeftButtonPressed || FocusManager.Instance?.Current is TextBox) if (!properties.IsLeftButtonPressed || focusManager?.GetFocusedElement() is TextBox)
return; return;
if (_triggerEvent is null) if (_triggerEvent is null)

View File

@ -1,5 +1,4 @@
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
namespace Artemis.UI.DefaultTypes.PropertyInput; namespace Artemis.UI.DefaultTypes.PropertyInput;
@ -16,6 +15,6 @@ public partial class StringPropertyInputView : ReactiveUserControl<FloatProperty
private void OnRoutedKeyUp(object? sender, KeyEventArgs e) private void OnRoutedKeyUp(object? sender, KeyEventArgs e)
{ {
if (e.Key == Key.Enter || e.Key == Key.Escape) if (e.Key == Key.Enter || e.Key == Key.Escape)
FocusManager.Instance!.Focus(null); Focus();
} }
} }

View File

@ -8,7 +8,7 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.MenuBar.MenuBarView" x:Class="Artemis.UI.Screens.ProfileEditor.MenuBar.MenuBarView"
x:DataType="menuBar:MenuBarViewModel"> x:DataType="menuBar:MenuBarViewModel">
<Menu VerticalAlignment="Top" MenuClosed="MenuBase_OnMenuClosed"> <Menu VerticalAlignment="Top" Closed="MenuBase_OnMenuClosed">
<MenuItem Header="_File"> <MenuItem Header="_File">
<MenuItem Header="New"> <MenuItem Header="New">
<MenuItem.Icon> <MenuItem.Icon>

View File

@ -63,7 +63,12 @@ public partial class VisualEditorView : ReactiveUserControl<VisualEditorViewMode
private void UpdateZoomBorderBackground() private void UpdateZoomBorderBackground()
{ {
if (ZoomBorder.Background is VisualBrush visualBrush) if (ZoomBorder.Background is VisualBrush visualBrush)
{
visualBrush.DestinationRect = new RelativeRect(ZoomBorder.OffsetX * -1, ZoomBorder.OffsetY * -1, 20, 20, RelativeUnit.Absolute); visualBrush.DestinationRect = new RelativeRect(ZoomBorder.OffsetX * -1, ZoomBorder.OffsetY * -1, 20, 20, RelativeUnit.Absolute);
// Workaround
// This fixes an issue where the container is not invalidated, which leaves behind a 'smear' since Avalonia 11 rc1, check if still required later
ZoomBorder.InvalidateVisual();
}
} }

View File

@ -110,14 +110,14 @@
</shared:SelectionRectangle.Background> </shared:SelectionRectangle.Background>
</shared:SelectionRectangle> </shared:SelectionRectangle>
<Border Name="SurfaceBounds" <Rectangle Name="SurfaceBounds"
VerticalAlignment="Top" VerticalAlignment="Top"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Width="{Binding MaxTextureSize}" Width="{Binding MaxTextureSize}"
Height="{Binding MaxTextureSize}" Height="{Binding MaxTextureSize}"
BorderThickness="2" StrokeThickness="2"
BorderBrush="{DynamicResource SystemAccentColorLight1}" Stroke="{DynamicResource SystemAccentColorLight1}"
BorderDashArray="6,2" StrokeDashArray="6,2"
Opacity="0.5" /> Opacity="0.5" />
</Grid> </Grid>
</paz:ZoomBorder> </paz:ZoomBorder>

View File

@ -5,7 +5,6 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.PanAndZoom; using Avalonia.Controls.PanAndZoom;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
@ -30,7 +29,7 @@ public partial class SurfaceEditorView : ReactiveUserControl<SurfaceEditorViewMo
private void ZoomBorder_OnZoomChanged(object sender, ZoomChangedEventArgs e) private void ZoomBorder_OnZoomChanged(object sender, ZoomChangedEventArgs e)
{ {
UpdateZoomBorderBackground(); UpdateZoomBorderBackground();
SurfaceBounds.BorderThickness = new Thickness(2 / ContainerZoomBorder.ZoomX); SurfaceBounds.StrokeThickness = 2 / ContainerZoomBorder.ZoomX;
} }
private void SelectionRectangle_OnSelectionUpdated(object? sender, SelectionRectangleEventArgs e) private void SelectionRectangle_OnSelectionUpdated(object? sender, SelectionRectangleEventArgs e)
@ -49,6 +48,11 @@ public partial class SurfaceEditorView : ReactiveUserControl<SurfaceEditorViewMo
private void UpdateZoomBorderBackground() private void UpdateZoomBorderBackground()
{ {
if (ContainerZoomBorder.Background is VisualBrush visualBrush) if (ContainerZoomBorder.Background is VisualBrush visualBrush)
{
visualBrush.DestinationRect = new RelativeRect(ContainerZoomBorder.OffsetX * -1, ContainerZoomBorder.OffsetY * -1, 20, 20, RelativeUnit.Absolute); visualBrush.DestinationRect = new RelativeRect(ContainerZoomBorder.OffsetX * -1, ContainerZoomBorder.OffsetY * -1, 20, 20, RelativeUnit.Absolute);
// Workaround
// This fixes an issue where the container is not invalidated, which leaves behind a 'smear' since Avalonia 11 rc1, check if still required later
ContainerZoomBorder.InvalidateVisual();
}
} }
} }

View File

@ -3,30 +3,28 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
using Avalonia.Rendering; using Avalonia.Threading;
using Avalonia.VisualTree; using Avalonia.VisualTree;
namespace Artemis.UI.Screens.VisualScripting.Pins; namespace Artemis.UI.Screens.VisualScripting.Pins;
public class PinView : ReactiveUserControl<PinViewModel> public class PinView : ReactiveUserControl<PinViewModel>
{ {
private Canvas? _container; private readonly DispatcherTimer _updateTimer;
private bool _dragging; private bool _dragging;
private Canvas? _container;
private Border? _pinPoint; private Border? _pinPoint;
private PinViewRenderLoopTaks _renderLoopTask;
public PinView()
{
_updateTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(16), DispatcherPriority.Render, UpdatePosition);
}
protected void InitializePin(Border pinPoint) protected void InitializePin(Border pinPoint)
{ {
_pinPoint = pinPoint; _pinPoint = pinPoint;
_pinPoint.PointerMoved += PinPointOnPointerMoved; _pinPoint.PointerMoved += PinPointOnPointerMoved;
_pinPoint.PointerReleased += PinPointOnPointerReleased; _pinPoint.PointerReleased += PinPointOnPointerReleased;
_pinPoint.PropertyChanged += PinPointOnPropertyChanged;
_renderLoopTask = new PinViewRenderLoopTaks(this);
}
private void PinPointOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
Console.WriteLine(e);
} }
private void PinPointOnPointerMoved(object? sender, PointerEventArgs e) private void PinPointOnPointerMoved(object? sender, PointerEventArgs e)
@ -74,19 +72,17 @@ public class PinView : ReactiveUserControl<PinViewModel>
/// <inheritdoc /> /// <inheritdoc />
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{ {
base.OnAttachedToVisualTree(e);
_container = this.FindAncestorOfType<Canvas>(); _container = this.FindAncestorOfType<Canvas>();
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>().Add(_renderLoopTask); _updateTimer.Start();
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{ {
base.OnDetachedFromVisualTree(e); _updateTimer.Stop();
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>().Remove(_renderLoopTask);
} }
public void UpdatePosition() public void UpdatePosition(object? sender, EventArgs eventArgs)
{ {
if (_container == null || _pinPoint == null || ViewModel == null) if (_container == null || _pinPoint == null || ViewModel == null)
return; return;
@ -98,24 +94,3 @@ public class PinView : ReactiveUserControl<PinViewModel>
#endregion #endregion
} }
public class PinViewRenderLoopTaks : IRenderLoopTask
{
private readonly PinView _pinView;
public PinViewRenderLoopTaks(PinView pinView)
{
_pinView = pinView;
}
public void Update(TimeSpan time)
{
_pinView.UpdatePosition();
}
public void Render()
{
}
public bool NeedsUpdate => true;
}

View File

@ -8,9 +8,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-preview8" /> <PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-rc1.1" />
<PackageReference Include="DryIoc.dll" Version="5.4.0" /> <PackageReference Include="DryIoc.dll" Version="5.4.0" />
<PackageReference Include="NoStringEvaluating" Version="2.5.2" /> <PackageReference Include="NoStringEvaluating" Version="2.5.2" />
<PackageReference Include="ReactiveUI" Version="18.4.26" /> <PackageReference Include="ReactiveUI" Version="18.4.26" />

View File

@ -12,7 +12,6 @@ public class DataModelEventCycleNode : Node<DataModelPathEntity, DataModelEventC
private Type _currentType; private Type _currentType;
private DataModelPath? _dataModelPath; private DataModelPath? _dataModelPath;
private object? _lastPathValue; private object? _lastPathValue;
private DateTime _lastTrigger;
private bool _updating; private bool _updating;
public DataModelEventCycleNode() public DataModelEventCycleNode()
@ -22,8 +21,8 @@ public class DataModelEventCycleNode : Node<DataModelPathEntity, DataModelEventC
CycleValues = CreateInputPinCollection(typeof(object), "", 0); CycleValues = CreateInputPinCollection(typeof(object), "", 0);
Output = CreateOutputPin(typeof(object)); Output = CreateOutputPin(typeof(object));
CycleValues.PinAdded += CycleValuesOnPinAdded; CycleValues.PinAdded += OnCycleValuesOnPinAdded;
CycleValues.PinRemoved += CycleValuesOnPinRemoved; CycleValues.PinRemoved += OnCycleValuesOnPinRemoved;
CycleValues.Add(CycleValues.CreatePin()); CycleValues.Add(CycleValues.CreatePin());
// Monitor storage for changes // Monitor storage for changes
@ -39,24 +38,15 @@ public class DataModelEventCycleNode : Node<DataModelPathEntity, DataModelEventC
{ {
Script = script; Script = script;
if (Storage == null) if (Storage != null)
return; UpdateDataModelPath();
UpdateDataModelPath();
} }
public override void Evaluate() public override void Evaluate()
{ {
object? pathValue = _dataModelPath?.GetValue(); object? pathValue = _dataModelPath?.GetValue();
bool hasTriggered = pathValue is IDataModelEvent dataModelEvent ? EvaluateEvent(dataModelEvent) : EvaluateValue(pathValue); if (pathValue is not IDataModelEvent && EvaluateValue(pathValue))
Cycle();
if (hasTriggered)
{
_currentIndex++;
if (_currentIndex >= CycleValues.Count())
_currentIndex = 0;
}
object? outputValue = CycleValues.ElementAt(_currentIndex).PinValue; object? outputValue = CycleValues.ElementAt(_currentIndex).PinValue;
if (Output.Type.IsInstanceOfType(outputValue)) if (Output.Type.IsInstanceOfType(outputValue))
@ -65,15 +55,6 @@ public class DataModelEventCycleNode : Node<DataModelPathEntity, DataModelEventC
Output.Value = Output.Type.GetDefault()!; Output.Value = Output.Type.GetDefault()!;
} }
private bool EvaluateEvent(IDataModelEvent dataModelEvent)
{
if (dataModelEvent.LastTrigger <= _lastTrigger)
return false;
_lastTrigger = dataModelEvent.LastTrigger;
return true;
}
private bool EvaluateValue(object? pathValue) private bool EvaluateValue(object? pathValue)
{ {
if (Equals(pathValue, _lastPathValue)) if (Equals(pathValue, _lastPathValue))
@ -83,51 +64,26 @@ public class DataModelEventCycleNode : Node<DataModelPathEntity, DataModelEventC
return true; return true;
} }
private void CycleValuesOnPinAdded(object? sender, SingleValueEventArgs<IPin> e) private void Cycle()
{ {
e.Value.PinConnected += OnPinConnected; _currentIndex++;
e.Value.PinDisconnected += OnPinDisconnected;
}
private void CycleValuesOnPinRemoved(object? sender, SingleValueEventArgs<IPin> e) if (_currentIndex >= CycleValues.Count())
{ _currentIndex = 0;
e.Value.PinConnected -= OnPinConnected;
e.Value.PinDisconnected -= OnPinDisconnected;
}
private void OnPinDisconnected(object? sender, SingleValueEventArgs<IPin> e)
{
ProcessPinDisconnected();
}
private void OnPinConnected(object? sender, SingleValueEventArgs<IPin> e)
{
ProcessPinConnected(e.Value);
}
private void ProcessPinConnected(IPin source)
{
if (_updating)
return;
try
{
_updating = true;
// No need to change anything if the types haven't changed
if (_currentType != source.Type)
ChangeCurrentType(source.Type);
}
finally
{
_updating = false;
}
} }
private void UpdateDataModelPath() private void UpdateDataModelPath()
{ {
DataModelPath? old = _dataModelPath; DataModelPath? old = _dataModelPath;
if (old?.GetValue() is IDataModelEvent oldEvent)
oldEvent.EventTriggered -= OnEventTriggered;
_dataModelPath = Storage != null ? new DataModelPath(Storage) : null; _dataModelPath = Storage != null ? new DataModelPath(Storage) : null;
if (_dataModelPath?.GetValue() is IDataModelEvent newEvent)
newEvent.EventTriggered += OnEventTriggered;
old?.Dispose(); old?.Dispose();
} }
@ -139,10 +95,28 @@ public class DataModelEventCycleNode : Node<DataModelPathEntity, DataModelEventC
_currentType = type; _currentType = type;
} }
private void ProcessPinDisconnected() private void OnEventTriggered(object? sender, EventArgs e)
{
Cycle();
}
private void OnCycleValuesOnPinAdded(object? sender, SingleValueEventArgs<IPin> e)
{
e.Value.PinConnected += OnPinConnected;
e.Value.PinDisconnected += OnPinDisconnected;
}
private void OnCycleValuesOnPinRemoved(object? sender, SingleValueEventArgs<IPin> e)
{
e.Value.PinConnected -= OnPinConnected;
e.Value.PinDisconnected -= OnPinDisconnected;
}
private void OnPinDisconnected(object? sender, SingleValueEventArgs<IPin> e)
{ {
if (_updating) if (_updating)
return; return;
try try
{ {
// If there's still a connected pin, stick to the current type // If there's still a connected pin, stick to the current type
@ -157,9 +131,30 @@ public class DataModelEventCycleNode : Node<DataModelPathEntity, DataModelEventC
} }
} }
private void OnPinConnected(object? sender, SingleValueEventArgs<IPin> e)
{
if (_updating)
return;
try
{
_updating = true;
// No need to change anything if the types haven't changed
if (_currentType != e.Value.Type)
ChangeCurrentType(e.Value.Type);
}
finally
{
_updating = false;
}
}
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public void Dispose()
{ {
if (_dataModelPath?.GetValue() is IDataModelEvent newEvent)
newEvent.EventTriggered -= OnEventTriggered;
_dataModelPath?.Dispose(); _dataModelPath?.Dispose();
} }
} }