Browse Source

Implemented ZIndex support

pull/8105/head
Nikita Tsukanov 4 years ago
parent
commit
0d7adc70d9
  1. 69
      src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
  2. 6
      src/Avalonia.Base/Rendering/ImmediateRenderer.cs
  3. 44
      src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs
  4. 8
      src/Avalonia.Base/Visual.cs
  5. 5
      src/Avalonia.Base/VisualTree/IVisual.cs

69
src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs

@ -4,6 +4,7 @@ using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using Avalonia.Collections;
using Avalonia.Collections.Pooled;
using Avalonia.Media;
using Avalonia.Rendering.Composition.Drawing;
using Avalonia.Rendering.Composition.Server;
@ -100,26 +101,74 @@ public class CompositingRenderer : RendererBase, IRendererWithCompositor
return;
var compositionChildren = v.CompositionVisual.Children;
var visualChildren = (AvaloniaList<IVisual>)v.GetVisualChildren();
PooledList<(IVisual visual, int index)>? sortedChildren = null;
if (v.HasNonUniformZIndexChildren && visualChildren.Count > 1)
{
sortedChildren = new (visualChildren.Count);
for (var c = 0; c < visualChildren.Count; c++)
sortedChildren.Add((visualChildren[c], c));
// Regular Array.Sort is unstable, we need to provide indices as well to avoid reshuffling elements.
sortedChildren.Sort(static (lhs, rhs) =>
{
var result = lhs.visual.ZIndex.CompareTo(rhs.visual.ZIndex);
return result == 0 ? lhs.index.CompareTo(rhs.index) : result;
});
}
if (compositionChildren.Count == visualChildren.Count)
{
bool mismatch = false;
for(var c=0; c<visualChildren.Count; c++)
if(!object.ReferenceEquals(compositionChildren[c], ((Visual)visualChildren[c]).CompositionVisual))
if (v.HasNonUniformZIndexChildren)
{
}
if (sortedChildren != null)
for (var c = 0; c < visualChildren.Count; c++)
{
mismatch = true;
break;
if (!ReferenceEquals(compositionChildren[c], ((Visual)sortedChildren[c].visual).CompositionVisual))
{
mismatch = true;
break;
}
}
if(!mismatch)
else
for (var c = 0; c < visualChildren.Count; c++)
if (!ReferenceEquals(compositionChildren[c], ((Visual)visualChildren[c]).CompositionVisual))
{
mismatch = true;
break;
}
if (!mismatch)
{
sortedChildren?.Dispose();
return;
}
}
compositionChildren.Clear();
foreach (var ch in v.GetVisualChildren())
if (sortedChildren != null)
{
var compositionChild = ((Visual)ch).CompositionVisual;
if (compositionChild != null)
compositionChildren.Add(compositionChild);
foreach (var ch in sortedChildren)
{
var compositionChild = ((Visual)ch.visual).CompositionVisual;
if (compositionChild != null)
compositionChildren.Add(compositionChild);
}
sortedChildren.Dispose();
}
else
foreach (var ch in v.GetVisualChildren())
{
var compositionChild = ((Visual)ch).CompositionVisual;
if (compositionChild != null)
compositionChildren.Add(compositionChild);
}
}
private void Update()

6
src/Avalonia.Base/Rendering/ImmediateRenderer.cs

@ -329,7 +329,11 @@ namespace Avalonia.Rendering
if (_updateTransformedBounds)
visual.TransformedBounds = transformed;
foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance))
var childrenEnumerable = visual.HasNonUniformZIndexChildren
? visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance)
: (IEnumerable<IVisual>)visual.VisualChildren;
foreach (var child in childrenEnumerable)
{
var childBounds = GetTransformedBounds(child);

44
src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs

@ -272,26 +272,36 @@ namespace Avalonia.Rendering.SceneGraph
else if (visualChildren.Count > 1)
{
var count = visualChildren.Count;
var sortedChildren = new (IVisual visual, int index)[count];
for (var i = 0; i < count; i++)
if (visual.HasNonUniformZIndexChildren)
{
sortedChildren[i] = (visualChildren[i], i);
}
// Regular Array.Sort is unstable, we need to provide indices as well to avoid reshuffling elements.
Array.Sort(sortedChildren, (lhs, rhs) =>
{
var result = ZIndexComparer.Instance.Compare(lhs.visual, rhs.visual);
return result == 0 ? lhs.index.CompareTo(rhs.index) : result;
});
foreach (var child in sortedChildren)
{
var childNode = GetOrCreateChildNode(scene, child.Item1, node);
Update(context, scene, (VisualNode)childNode, clip, forceRecurse);
var sortedChildren = new (IVisual visual, int index)[count];
for (var i = 0; i < count; i++)
{
sortedChildren[i] = (visualChildren[i], i);
}
// Regular Array.Sort is unstable, we need to provide indices as well to avoid reshuffling elements.
Array.Sort(sortedChildren, (lhs, rhs) =>
{
var result = ZIndexComparer.Instance.Compare(lhs.visual, rhs.visual);
return result == 0 ? lhs.index.CompareTo(rhs.index) : result;
});
foreach (var child in sortedChildren)
{
var childNode = GetOrCreateChildNode(scene, child.Item1, node);
Update(context, scene, (VisualNode)childNode, clip, forceRecurse);
}
}
else
foreach (var child in visualChildren)
{
var childNode = GetOrCreateChildNode(scene, child, node);
Update(context, scene, (VisualNode)childNode, clip, forceRecurse);
}
}
node.SubTreeUpdated = true;

8
src/Avalonia.Base/Visual.cs

@ -293,6 +293,8 @@ namespace Avalonia
internal CompositionDrawListVisual? CompositionVisual { get; private set; }
public bool HasNonUniformZIndexChildren { get; private set; }
/// <summary>
/// Gets a value indicating whether this control is attached to a visual root.
/// </summary>
@ -445,6 +447,9 @@ namespace Avalonia
AttachedToVisualTree?.Invoke(this, e);
InvalidateVisual();
if (ZIndex != 0 && this.GetVisualParent() is Visual parent)
parent.HasNonUniformZIndexChildren = true;
var visualChildren = VisualChildren;
if (visualChildren != null)
@ -611,6 +616,9 @@ namespace Avalonia
{
var sender = e.Sender as IVisual;
var parent = sender?.VisualParent;
if (sender?.ZIndex != 0 && parent is Visual parentVisual)
parentVisual.HasNonUniformZIndexChildren = true;
sender?.InvalidateVisual();
parent?.VisualRoot?.Renderer?.RecalculateChildren(parent);
}

5
src/Avalonia.Base/VisualTree/IVisual.cs

@ -79,6 +79,11 @@ namespace Avalonia.VisualTree
/// Gets a value indicating whether to apply mirror transform on this control.
/// </summary>
bool HasMirrorTransform { get; }
/// <summary>
/// Gets a value indicating whether to sort children when rendering this control
/// </summary>
bool HasNonUniformZIndexChildren { get; }
/// <summary>
/// Gets or sets the render transform of the control.

Loading…
Cancel
Save