From c5b7833f7cc4511177ec9a1929b2b48d51b2792e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Sepulchre?= Date: Sat, 26 Oct 2024 11:28:54 +0200 Subject: [PATCH 1/4] Update README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c6659f797..6c4393c52 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,13 @@
-## ✨ 6.0 Release +## ✨ 6.0 Release Candidate -.. Coming soon .. +I’m pleased to announce the 6.0 Release Candidate. This is our biggest release yet, and after a long journey, the library is now close to the initial idealized vision I had for it. I’m happy to say that both the style and various APIs are now finalized. + +Moving forward, our focus will be on maintaining the library and potentially extending certain functionalities. No major changes are expected unless absolutely necessary. + +Massive thanks to [sirdoombox](https://github.com/sirdoombox) for his incredible work. Without him, this library would definitely not be the same.

## 📄 Documentation From 4bf06e97a5ecfea62d54f57583ec80572d7c18dd Mon Sep 17 00:00:00 2001 From: Peter Vietense Date: Fri, 8 Nov 2024 16:42:03 +0100 Subject: [PATCH 2/4] fix PropertyGrid not opening complex child viewmodel in new window, added sukihost support back --- .../ControlsLibrary/PropertyGridView.axaml | 31 +++++-- .../ControlsLibrary/PropertyGridView.axaml.cs | 17 ++++ .../PropertyGridTemplateSelector.axaml.cs | 92 +++++++++++++------ .../PropertyGrid/PropertyGridWindow.axaml | 25 +++-- 4 files changed, 114 insertions(+), 51 deletions(-) diff --git a/SukiUI.Demo/Features/ControlsLibrary/PropertyGridView.axaml b/SukiUI.Demo/Features/ControlsLibrary/PropertyGridView.axaml index 99a6faa10..efd35e490 100644 --- a/SukiUI.Demo/Features/ControlsLibrary/PropertyGridView.axaml +++ b/SukiUI.Demo/Features/ControlsLibrary/PropertyGridView.axaml @@ -1,27 +1,38 @@ + + + + - - - - - - + + + + + + + + + diff --git a/SukiUI.Demo/Features/ControlsLibrary/PropertyGridView.axaml.cs b/SukiUI.Demo/Features/ControlsLibrary/PropertyGridView.axaml.cs index 1c3857cbb..0ac9bc697 100644 --- a/SukiUI.Demo/Features/ControlsLibrary/PropertyGridView.axaml.cs +++ b/SukiUI.Demo/Features/ControlsLibrary/PropertyGridView.axaml.cs @@ -1,4 +1,7 @@ using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Interactivity; +using SukiUI.Controls; namespace SukiUI.Demo.Features.ControlsLibrary; @@ -8,4 +11,18 @@ public PropertyGridView() { InitializeComponent(); } + + private void ToggleButton_OnIsCheckedChanged(object? sender, RoutedEventArgs e) + { + if (sender is not ToggleButton toggleButton) + { + return; + } + + var resource = this.FindResource("PropertyGridTemplateSelector"); + if (resource is PropertyGridTemplateSelector templateSelector) + { + templateSelector.UseSukiHost = toggleButton.IsChecked == true; + } + } } \ No newline at end of file diff --git a/SukiUI/Controls/PropertyGrid/PropertyGridTemplateSelector.axaml.cs b/SukiUI/Controls/PropertyGrid/PropertyGridTemplateSelector.axaml.cs index 0836fc861..d1c5aaf16 100644 --- a/SukiUI/Controls/PropertyGrid/PropertyGridTemplateSelector.axaml.cs +++ b/SukiUI/Controls/PropertyGrid/PropertyGridTemplateSelector.axaml.cs @@ -1,4 +1,6 @@ -using Avalonia.Controls; +using System.Linq; +using System.Threading.Tasks; +using Avalonia.Controls; using Avalonia.Controls.Templates; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; @@ -9,8 +11,10 @@ namespace SukiUI.Controls; public partial class PropertyGridTemplateSelector : ResourceDictionary, IDataTemplate { + public SukiDialogHost? SukiDialogHost { get; set; } + public bool UseSukiHost { get; set; } = true; - + public PropertyGridTemplateSelector() { InitializeComponent(); @@ -57,46 +61,80 @@ public bool Match(object? data) return false; } - if (ContainsKey(key) == false) + return ContainsKey(key) != false; + } + + private static void ShowSukiHostDialog(ISukiDialogManager manager, ComplexTypeViewModel viewModel) + { + manager + .CreateDialog() + .WithContent(new PropertyGridDialog() + { + DataContext = viewModel.Value + }) + .WithTitle(viewModel.DisplayName) + .Dismiss().ByClickingBackground() + .TryShow(); + } + + private static async Task ShowWindowDialogAsync(Control control) + { + var root = control.GetVisualRoot(); + if (root is not Window parentWindow || control.DataContext is not ComplexTypeViewModel childViewModel || childViewModel.Value is null) { - return false; + return; } - return true; + var window = new PropertyGridWindow() + { + DataContext = childViewModel.Value, + Title = childViewModel.DisplayName, + }; + + await window.ShowDialog(parentWindow); } - private async void OnMoreInfoClick(object sender, RoutedEventArgs e) + protected virtual async void OnMoreInfoClick(object sender, RoutedEventArgs e) { if (sender is not Control control) { return; } - // TODO: No longer possible to just statically use SukiHost to show dialogs. - // if (UseSukiHost) - // { - // if (control.DataContext is not ComplexTypeViewModel childViewModel || childViewModel.Value is null) - // { - // return; - // } - // SukiHost.ShowDialog(new PropertyGridDialog() - // { - // DataContext = childViewModel.Value - // }, true, true); - // } - else + + var sukiDialogHost = SukiDialogHost; + if (UseSukiHost) { - var root = control.GetVisualRoot(); - if (root is not Window parentWindow || control.DataContext is not ComplexTypeViewModel childViewModel || childViewModel.Value is null) + if (sukiDialogHost is not null) { - return; - } + if (control.DataContext is not ComplexTypeViewModel childViewModel || childViewModel.Value is null) + { + return; + } - var window = new PropertyGridWindow() + ShowSukiHostDialog(sukiDialogHost.Manager, childViewModel); + } + else { - DataContext = childViewModel, - }; + var root = control.GetVisualRoot(); + if (root is not SukiWindow parentWindow || control.DataContext is not ComplexTypeViewModel childViewModel || childViewModel.Value is null) + { + return; + } - await window.ShowDialog(parentWindow); + sukiDialogHost = parentWindow.Hosts.Where(p => p is SukiDialogHost).Cast().FirstOrDefault(); + if (sukiDialogHost is not null) + { + ShowSukiHostDialog(sukiDialogHost.Manager, childViewModel); + } + else + { + await ShowWindowDialogAsync(control); + } + } + } + else + { + await ShowWindowDialogAsync(control); } } } \ No newline at end of file diff --git a/SukiUI/Controls/PropertyGrid/PropertyGridWindow.axaml b/SukiUI/Controls/PropertyGrid/PropertyGridWindow.axaml index aae9fc462..c35052476 100644 --- a/SukiUI/Controls/PropertyGrid/PropertyGridWindow.axaml +++ b/SukiUI/Controls/PropertyGrid/PropertyGridWindow.axaml @@ -4,7 +4,6 @@ xmlns:controls="clr-namespace:SukiUI.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - Title="{Binding DisplayName}" Width="400" Height="500" d:DesignHeight="400" @@ -14,20 +13,18 @@ mc:Ignorable="d"> - - - - + + + - + - - - - - + + + + From 265367e8af996ac43fe7b9c64d21e1707f20f4d1 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 11 Nov 2024 14:58:12 +0000 Subject: [PATCH 3/4] Simplify `Flat` shader. Include `Background` docks page. --- SukiUI/Content/Shaders/Background/flat.sksl | 4 -- docs/docs/.vitepress/config/en.mts | 1 + docs/docs/documentation/theming/background.md | 54 +++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 docs/docs/documentation/theming/background.md diff --git a/SukiUI/Content/Shaders/Background/flat.sksl b/SukiUI/Content/Shaders/Background/flat.sksl index c671dcff3..a468ad30d 100644 --- a/SukiUI/Content/Shaders/Background/flat.sksl +++ b/SukiUI/Content/Shaders/Background/flat.sksl @@ -1,7 +1,3 @@ vec4 main(vec2 fragCoord) { - - if(iDark == 1) - return vec4(iBase * 1, iAlpha); - return vec4(iBase, iAlpha); } \ No newline at end of file diff --git a/docs/docs/.vitepress/config/en.mts b/docs/docs/.vitepress/config/en.mts index 904db0507..22fb55009 100644 --- a/docs/docs/.vitepress/config/en.mts +++ b/docs/docs/.vitepress/config/en.mts @@ -23,6 +23,7 @@ export const en = defineConfig({ { text: 'Basic', link: '/documentation/theming/basic' }, { text: 'Light & Dark', link: '/documentation/theming/theme' }, { text: 'Color', link: '/documentation/theming/theme-color' }, + { text: 'Background', link: '/documentation/theming/background' }, ] }, { diff --git a/docs/docs/documentation/theming/background.md b/docs/docs/documentation/theming/background.md new file mode 100644 index 000000000..77c3ede7f --- /dev/null +++ b/docs/docs/documentation/theming/background.md @@ -0,0 +1,54 @@ +# Backgrounds + +SukiUI includes a background renderer which utilises GPU acceleration and shaders to draw complex runtime background effects that update with theme changes. All properties mentioned on this page can be accessed out of the box via the `Background{Property}` properties present in `SukiWindow`. If you wish to host a `SukiBackground` control of your own in another context then these properties should be similarly named without the `Background` prefix. + +## Styles + +Changing style to one of the defaults is done via `BackgroundStyle` - Available out of the box are `Gradient`, `Flat` and `Bubble`. It is possible however to use custom shaders (written in SKSL) to create your own backgrounds. There are two methods to use your own shaders written in this language: + +#### BackgroundShaderFile +By including an embedded resource in your application with the correct file extension (E.G. `MyShader.sksl`) it is possibly to simply set the `BackgroundShaderFile` property to the name of the file (without the extension). SukiUI will search your embedded resources for the file and load the shader for use automatically. + +SukiUI includes a few shaders that are not included in the default enum but are nonetheless accessible this way including `Cells` and `Waves`. + +#### BackgroundShaderCode +Simply assigning a string representing your shader to this property will create the runtime effect and render it without the need for embedded files, it is possible to bind to this property and dynamically alter the shader code at runtime if you so desire, any change will be reflected immediately. + +#### Notes +When choosing which background style to render, if more than one property is assigned to a non-null value at once, then SukiUI will prioritize the properties in the following order `BackgroundShaderFile` -> `BackgroundShaderCode` -> `BackgroundStyle` + +## Custom Styles + +In order to render custom backgrounds via the properties mentioned before, it is necessary to write SKSL. This might seem daunting at first but it is a fairly simple language in which you write an entry point function that returns a `vec4` representing the colour of each pixel. With GPU parallelization it is possible to execute large numbers of fairly complex mathematical calculations very quickly. + +SukiUI automatically includes a set of uniforms in these effects before shader compilation for you to use in your shaders, these are: + +- `float iTime` - A representation of the current ticks since the background began rendering. Only changed when animation is enabled. +- `float iDark` - Whether the application is in light or dark mode - 0 = light, 1 = dark. +- `float iAlpha` - The alpha at which the background is being drawn, largely controlled by opacity of the background control. +- `vec3 iResolution` - The resolution of the background in pixels, `x` and `y` are the only elements used, `z` is always 0. +- `vec3 iPrimary` - A (not exact) representation of the current active primary theme color. +- `vec3 iAccent` - A (not exact) representation of the current active accent theme color. +- `vec3 iBase` - A pre-calculated background colour for the theme - or an off-white if the app is in light mode. + +These uniforms are included automatically in any shader file or code you supply and can be used as if they were globally scoped variables. They are updated per-frame and any change in the application state will be reflected in these uniforms. + +The simplest example of a shader is our `Flat` style which simply returns the base background colour for every pixel. + +```glsl +vec4 main(vec2 fragCoord) { + return vec4(iBase, iAlpha); +} +``` + +## Transitions + +Enabling `BackgroundTransitionsEnabled` will cause any change in the background style to "fade" between the two with a simple opacity switch, this is where the `iAlpha` property is mostly used. `BackgroundTransitionTime` can also be set to define the time in seconds for the transition (default: 1 second). + +## Animation + +The background renderer does support animation via `BackgroundAnimationEnabled` and will run at native framerates, however due to the need to invalidate the entire visual tree every frame this can be extremely costly (a bump of roughly 5% CPU utilisation and upwards of 20% GPU utilisation depending on your hardware) - only use this if you are clearly aware of the cost involved. + +## Software fallback + +In the case SkiaSharp (Avalonia's underlying rendering engine) is unable to find any usable hardware acceleration, SukiUI will fall back to a software rendering solution which is simply the `Flat` background style rendered on the CPU. \ No newline at end of file From c6a44b08b3bc9b119318674cd65f747ecc2ccf5d Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 11 Nov 2024 15:03:06 +0000 Subject: [PATCH 4/4] Reformat warning about animations. --- docs/docs/documentation/theming/background.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/docs/documentation/theming/background.md b/docs/docs/documentation/theming/background.md index 77c3ede7f..7be992936 100644 --- a/docs/docs/documentation/theming/background.md +++ b/docs/docs/documentation/theming/background.md @@ -47,7 +47,11 @@ Enabling `BackgroundTransitionsEnabled` will cause any change in the background ## Animation -The background renderer does support animation via `BackgroundAnimationEnabled` and will run at native framerates, however due to the need to invalidate the entire visual tree every frame this can be extremely costly (a bump of roughly 5% CPU utilisation and upwards of 20% GPU utilisation depending on your hardware) - only use this if you are clearly aware of the cost involved. +The background renderer does support animation via `BackgroundAnimationEnabled` and will run at native framerates, all default SukiUI backgrounds support animation out of the box (except for `Flat`). + +::: warning +Due to the need for an invalidation and repaint of the entire visual tree, animations can have a significant impact on performance and it is recommended that you only use it if absolutely necessary. In limited testing we see a roughly 5% bump in CPU and 20% bump in GPU utilization _at all times_ when animation is enabled. +::: ## Software fallback