Files
MicrosoftIris/UIX.RenderApi.OpenGL/Scene/GLVisualContainer.cs
T

87 lines
2.9 KiB
C#

using System.Collections.Generic;
using Silk.NET.Maths;
namespace Microsoft.Iris.Render.OpenGL
{
/// <summary>
/// A transform/grouping node in the visual tree. Renders its children in
/// ascending <see cref="GLVisual.Layer"/> order after applying its own transform.
/// </summary>
public sealed class GLVisualContainer : GLVisual, IVisualContainer
{
private readonly List<GLVisual> m_children = new List<GLVisual>();
private readonly bool m_isRoot;
public GLVisualContainer(GLRenderSession session, object ownerData, bool isRoot)
: base(session, ownerData)
{
m_isRoot = isRoot;
}
public bool IsRoot => m_isRoot;
public int ChildCount => m_children.Count;
public ICamera? Camera { get; set; }
public void AddChild(IVisual vChild, IVisual vSibling, VisualOrder nOrder)
{
if (vChild is not GLVisual child)
return;
child.ParentContainer?.RemoveChild(child);
child.ParentContainer = this;
int siblingIndex = vSibling is GLVisual s ? m_children.IndexOf(s) : -1;
switch (nOrder)
{
case VisualOrder.First:
m_children.Insert(0, child);
break;
case VisualOrder.Before when siblingIndex >= 0:
m_children.Insert(siblingIndex, child);
break;
case VisualOrder.After when siblingIndex >= 0:
m_children.Insert(siblingIndex + 1, child);
break;
default: // Any, Last, or unresolved sibling
m_children.Add(child);
break;
}
child.RegisterUsage(this);
}
public void RemoveChild(IVisual vChild)
{
if (vChild is GLVisual child && m_children.Remove(child))
{
child.ParentContainer = null;
child.UnregisterUsage(this);
}
}
public void RemoveAllChildren()
{
// Snapshot: UnregisterUsage can trigger disposal which mutates state.
foreach (GLVisual child in m_children.ToArray())
RemoveChild(child);
}
internal override void Render(SceneRenderer renderer, Matrix4X4<float> parentMatrix, float inheritedAlpha)
{
if (!Visible)
return;
Matrix4X4<float> matrix = LocalMatrix * parentMatrix;
float alpha = inheritedAlpha * Alpha;
// Draw children back-to-front by layer. OrderBy is stable, preserving
// insertion order within a layer.
m_children.Sort((a, b) => a.Layer.CompareTo(b.Layer));
foreach (GLVisual child in m_children)
child.Render(renderer, matrix, alpha);
}
protected override void DisposeCore() => RemoveAllChildren();
}
}