mirror of
https://github.com/ZuneDev/MicrosoftIris.git
synced 2026-07-27 13:13:29 -07:00
87 lines
2.9 KiB
C#
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();
|
|
}
|
|
}
|