diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs
index ecab68953..36f107598 100644
--- a/src/Artemis.Core/Models/Profile/Folder.cs
+++ b/src/Artemis.Core/Models/Profile/Folder.cs
@@ -176,7 +176,7 @@ namespace Artemis.Core
#region Rendering
///
- public override void Render(SKCanvas canvas, SKPointI basePosition)
+ public override void Render(SKCanvas canvas, SKPointI basePosition, ProfileElement? editorFocus)
{
if (Disposed)
throw new ObjectDisposedException("Folder");
@@ -188,6 +188,10 @@ namespace Artemis.Core
// No point rendering if all children are disabled
if (!Children.Any(c => c is RenderProfileElement {Enabled: true}))
return;
+
+ // If the editor focus is on this folder, discard further focus for children to effectively focus the entire folder and all descendants
+ if (editorFocus == this)
+ editorFocus = null;
SKPaint layerPaint = new() {FilterQuality = SKFilterQuality.Low};
try
@@ -208,7 +212,7 @@ namespace Artemis.Core
// Iterate the children in reverse because the first layer must be rendered last to end up on top
for (int index = Children.Count - 1; index > -1; index--)
- Children[index].Render(canvas, new SKPointI(Bounds.Left, Bounds.Top));
+ Children[index].Render(canvas, new SKPointI(Bounds.Left, Bounds.Top), editorFocus);
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
{
diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs
index ca5f0d84c..7f2be3fb5 100644
--- a/src/Artemis.Core/Models/Profile/Layer.cs
+++ b/src/Artemis.Core/Models/Profile/Layer.cs
@@ -416,11 +416,14 @@ namespace Artemis.Core
}
///
- public override void Render(SKCanvas canvas, SKPointI basePosition)
+ public override void Render(SKCanvas canvas, SKPointI basePosition, ProfileElement? editorFocus)
{
if (Disposed)
throw new ObjectDisposedException("Layer");
+ if (editorFocus != null && editorFocus != this)
+ return;
+
RenderLayer(canvas, basePosition);
RenderCopies(canvas, basePosition);
}
@@ -496,7 +499,7 @@ namespace Artemis.Core
private void RenderCopies(SKCanvas canvas, SKPointI basePosition)
{
for (int i = _renderCopies.Count - 1; i >= 0; i--)
- _renderCopies[i].Render(canvas, basePosition);
+ _renderCopies[i].Render(canvas, basePosition, null);
}
///
@@ -627,20 +630,31 @@ namespace Artemis.Core
if (LayerBrush == null)
throw new ArtemisCoreException("The layer is not yet ready for rendering");
- using SKAutoCanvasRestore _ = new(canvas);
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
{
if (!baseLayerEffect.Suspended)
baseLayerEffect.InternalPreProcess(canvas, bounds, layerPaint);
}
-
- canvas.ClipPath(renderPath);
- LayerBrush.InternalRender(canvas, bounds, layerPaint);
-
- foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
+
+ try
{
- if (!baseLayerEffect.Suspended)
- baseLayerEffect.InternalPostProcess(canvas, bounds, layerPaint);
+ canvas.SaveLayer(layerPaint);
+ canvas.ClipPath(renderPath);
+
+ // Restore the blend mode before doing the actual render
+ layerPaint.BlendMode = SKBlendMode.SrcOver;
+
+ LayerBrush.InternalRender(canvas, bounds, layerPaint);
+
+ foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
+ {
+ if (!baseLayerEffect.Suspended)
+ baseLayerEffect.InternalPostProcess(canvas, bounds, layerPaint);
+ }
+ }
+ finally
+ {
+ canvas.Restore();
}
}
diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs
index 6d2645f07..eaa4abce4 100644
--- a/src/Artemis.Core/Models/Profile/Profile.cs
+++ b/src/Artemis.Core/Models/Profile/Profile.cs
@@ -101,7 +101,7 @@ namespace Artemis.Core
}
///
- public override void Render(SKCanvas canvas, SKPointI basePosition)
+ public override void Render(SKCanvas canvas, SKPointI basePosition, ProfileElement? editorFocus)
{
lock (_lock)
{
@@ -112,7 +112,7 @@ namespace Artemis.Core
profileScript.OnProfileRendering(canvas, canvas.LocalClipBounds);
foreach (ProfileElement profileElement in Children)
- profileElement.Render(canvas, basePosition);
+ profileElement.Render(canvas, basePosition, editorFocus);
foreach (ProfileScript profileScript in Scripts)
profileScript.OnProfileRendered(canvas, canvas.LocalClipBounds);
diff --git a/src/Artemis.Core/Models/Profile/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs
index 11ba77cb6..83a131739 100644
--- a/src/Artemis.Core/Models/Profile/ProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs
@@ -105,9 +105,12 @@ namespace Artemis.Core
public abstract void Update(double deltaTime);
///
- /// Renders the element
+ /// Renders the element
///
- public abstract void Render(SKCanvas canvas, SKPointI basePosition);
+ /// The canvas to render upon.
+ /// The base position to use to translate relative positions to absolute positions.
+ /// An optional element to focus on while rendering (other elements will not render).
+ public abstract void Render(SKCanvas canvas, SKPointI basePosition, ProfileElement? editorFocus);
///
/// Resets the internal state of the element
diff --git a/src/Artemis.Core/Plugins/LayerBrushes/PerLedLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrushes/PerLedLayerBrush.cs
index cc8805173..cfaeb5a48 100644
--- a/src/Artemis.Core/Plugins/LayerBrushes/PerLedLayerBrush.cs
+++ b/src/Artemis.Core/Plugins/LayerBrushes/PerLedLayerBrush.cs
@@ -1,4 +1,5 @@
-using SkiaSharp;
+using System;
+using SkiaSharp;
namespace Artemis.Core.LayerBrushes
{
@@ -52,23 +53,24 @@ namespace Artemis.Core.LayerBrushes
TryOrBreak(() =>
{
+
+
for (int index = 0; index < Layer.Leds.Count; index++)
{
ArtemisLed artemisLed = Layer.Leds[index];
SKPoint renderPoint = points[index * 2 + 1];
if (!float.IsFinite(renderPoint.X) || !float.IsFinite(renderPoint.Y))
continue;
-
+
// Let the brush determine the color
- paint.Color = GetColor(artemisLed, renderPoint).WithAlpha(paint.Color.Alpha);
-
+ paint.Color = GetColor(artemisLed, renderPoint);
SKRect ledRectangle = SKRect.Create(
artemisLed.AbsoluteRectangle.Left - Layer.Bounds.Left,
artemisLed.AbsoluteRectangle.Top - Layer.Bounds.Top,
artemisLed.AbsoluteRectangle.Width,
artemisLed.AbsoluteRectangle.Height
);
-
+
canvas.DrawRect(ledRectangle, paint);
}
}, "Failed to render");
diff --git a/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs b/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
index d73a904e8..5e449f263 100644
--- a/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
@@ -34,6 +34,11 @@ namespace Artemis.Core.Services
/// Gets or sets a boolean indicating whether rendering should only be done for profiles being edited
///
bool RenderForEditor { get; set; }
+
+ ///
+ /// Gets or sets the profile element to focus on while rendering for the editor
+ ///
+ ProfileElement? EditorFocus { get; set; }
///
/// Activates the profile of the given with the currently active surface
diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs
index 12b212cd4..742a0b0ec 100644
--- a/src/Artemis.Core/Services/Storage/ProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/ProfileService.cs
@@ -190,6 +190,7 @@ namespace Artemis.Core.Services
public bool HotkeysEnabled { get; set; }
public bool RenderForEditor { get; set; }
+ public ProfileElement? EditorFocus { get; set; }
public void UpdateProfiles(double deltaTime)
{
@@ -247,7 +248,7 @@ namespace Artemis.Core.Services
ProfileConfiguration? editedProfileConfiguration = _profileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(p => p.IsBeingEdited);
if (editedProfileConfiguration != null)
{
- editedProfileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
+ editedProfileConfiguration.Profile?.Render(canvas, SKPointI.Empty, RenderForEditor ? EditorFocus : null);
return;
}
@@ -265,7 +266,7 @@ namespace Artemis.Core.Services
ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
// Ensure all criteria are met before rendering
if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && profileConfiguration.ActivationConditionMet)
- profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
+ profileConfiguration.Profile?.Render(canvas, SKPointI.Empty, null);
}
catch (Exception e)
{
diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs
index 14fd740e3..beba258d7 100644
--- a/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs
@@ -36,6 +36,7 @@ internal class ProfileEditorService : IProfileEditorService
private readonly SourceList _selectedKeyframes;
private readonly IWindowService _windowService;
private ProfileEditorCommandScope? _profileEditorHistoryScope;
+ private readonly PluginSetting _focusSelectedLayer;
public ProfileEditorService(ILogger logger,
IProfileService profileService,
@@ -43,7 +44,8 @@ internal class ProfileEditorService : IProfileEditorService
IRgbService rgbService,
ILayerBrushService layerBrushService,
IMainWindowService mainWindowService,
- IWindowService windowService)
+ IWindowService windowService,
+ ISettingsService settingsService)
{
_logger = logger;
_profileService = profileService;
@@ -51,7 +53,8 @@ internal class ProfileEditorService : IProfileEditorService
_rgbService = rgbService;
_layerBrushService = layerBrushService;
_windowService = windowService;
-
+ _focusSelectedLayer = settingsService.GetSetting("ProfileEditor.FocusSelectedLayer", false);
+
_tools = new SourceList();
_selectedKeyframes = new SourceList();
_tools.Connect().AutoRefreshOnObservable(t => t.WhenAnyValue(vm => vm.IsSelected)).Subscribe(OnToolSelected);
@@ -85,6 +88,7 @@ internal class ProfileEditorService : IProfileEditorService
// When the main window closes, stop editing
mainWindowService.MainWindowClosed += (_, _) => ChangeCurrentProfileConfiguration(null);
+ _focusSelectedLayer.SettingChanged += FocusSelectedLayerOnSettingChanged;
}
public IObservable ProfileConfiguration { get; }
@@ -152,6 +156,7 @@ internal class ProfileEditorService : IProfileEditorService
{
_selectedKeyframes.Clear();
_profileElementSubject.OnNext(renderProfileElement);
+ _profileService.EditorFocus = _focusSelectedLayer.Value ? renderProfileElement : null;
ChangeCurrentLayerProperty(null);
}
@@ -504,4 +509,9 @@ internal class ProfileEditorService : IProfileEditorService
TickProfileElement(child, time);
}
}
+
+ private void FocusSelectedLayerOnSettingChanged(object? sender, EventArgs e)
+ {
+ _profileService.EditorFocus = _focusSelectedLayer.Value ? _profileElementSubject.Value : null;
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs
index 4872f92bb..9a63f91a6 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs
@@ -88,7 +88,7 @@ public class MenuBarViewModel : ActivatableViewModelBase
public PluginSetting FocusSelectedLayer => _settingsService.GetSetting("ProfileEditor.FocusSelectedLayer", false);
public PluginSetting ShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
public PluginSetting ShowFullPaths => _settingsService.GetSetting("ProfileEditor.ShowFullPaths", false);
- public PluginSetting AlwaysShowValues => _settingsService.GetSetting("ProfileEditor.AlwaysShowValues", false);
+ public PluginSetting AlwaysShowValues => _settingsService.GetSetting("ProfileEditor.AlwaysShowValues", true);
public PluginSetting AlwaysApplyDataBindings => _settingsService.GetSetting("ProfileEditor.AlwaysApplyDataBindings", false);
public ProfileEditorHistory? History
diff --git a/src/Artemis.UI/Screens/VisualScripting/CableView.axaml b/src/Artemis.UI/Screens/VisualScripting/CableView.axaml
index 9f57e492e..b52b38de1 100644
--- a/src/Artemis.UI/Screens/VisualScripting/CableView.axaml
+++ b/src/Artemis.UI/Screens/VisualScripting/CableView.axaml
@@ -18,7 +18,8 @@
-