Created
April 14, 2023 11:07
-
-
Save smoogipoo/1dc881ed4deca7c6cee9d39c8dd806d1 to your computer and use it in GitHub Desktop.
Topological DrawNode Test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DrawFrame(); | |
void DrawFrame() | |
{ | |
DrawNode root = new CompositeDrawNode(0) | |
{ | |
Children = | |
{ | |
new DrawNode(1), | |
new BufferedDrawNode(2, new CompositeDrawNode(3) | |
{ | |
Children = | |
{ | |
new DrawNode(4), | |
new DrawNode(5), | |
new CompositeDrawNode(6) | |
{ | |
Children = | |
{ | |
new BufferedDrawNode(7, new DrawNode(8)) | |
} | |
} | |
} | |
}), | |
new DrawNode(9) | |
} | |
}; | |
// Gather events from all DrawNodes. This is a topologically sorted list. | |
List<IDrawNodeEvent> events = new List<IDrawNodeEvent>(); | |
root.CreateVisitor().Visit(root, events); | |
// And then... draw! | |
// -- First the framebuffers. | |
Console.WriteLine("-- FrameBuffer pass"); | |
foreach (var e in events.OfType<FrameBufferDrawEvent>().Reverse()) | |
{ | |
Console.WriteLine($"FrameBuffer({e.DrawNode.Index})"); | |
e.Action(e.DrawNode); | |
} | |
// -- Then the render passes. | |
// We only need the first DrawNode in this case, because we're still using the tree traversal. | |
DrawEvent? firstEvent = events.OfType<DrawEvent>().FirstOrDefault(); | |
if (firstEvent is DrawEvent first) | |
{ | |
Console.WriteLine("-- FtB pass"); | |
first.FrontToBackAction.Invoke(first.DrawNode); | |
Console.WriteLine("-- BtF pass"); | |
first.BackToFrontAction.Invoke(first.DrawNode); | |
} | |
} | |
public interface IDrawNodeEvent | |
{ | |
public DrawNode DrawNode { get; } | |
} | |
public record struct FrameBufferDrawEvent(DrawNode DrawNode, Action<DrawNode> Action) : IDrawNodeEvent; | |
public record struct DrawEvent(DrawNode DrawNode, Action<DrawNode> BackToFrontAction, Action<DrawNode> FrontToBackAction) : IDrawNodeEvent; | |
public class DrawNode | |
{ | |
public readonly int Index; // DEBUG ONLY. | |
public DrawNode(int index) | |
{ | |
Index = index; | |
} | |
public virtual DrawNodeVisitor CreateVisitor() => new DrawNodeVisitor(); | |
public virtual void Draw() | |
{ | |
Console.WriteLine($"Draw({Index})"); | |
} | |
public virtual void DrawOpaqueInterior() | |
{ | |
Console.WriteLine($"Draw({Index})"); | |
} | |
} | |
public class DrawNodeVisitor | |
{ | |
public void Visit(DrawNode drawNode, List<IDrawNodeEvent> events) | |
{ | |
VisitDrawNode(drawNode, events); | |
} | |
protected virtual void VisitDrawNode(DrawNode drawNode, List<IDrawNodeEvent> events) | |
{ | |
events.Add(new DrawEvent(drawNode, d => d.Draw(), d => d.DrawOpaqueInterior())); | |
} | |
} | |
public class CompositeDrawNode : DrawNode | |
{ | |
public readonly List<DrawNode> Children = new List<DrawNode>(); | |
public CompositeDrawNode(int index) | |
: base(index) | |
{ | |
} | |
public override void Draw() | |
{ | |
base.Draw(); | |
for (int i = 0; i < Children.Count; i++) | |
Children[i].Draw(); | |
} | |
public override void DrawOpaqueInterior() | |
{ | |
for (int i = Children.Count - 1; i >= 0; i--) | |
Children[i].DrawOpaqueInterior(); | |
base.DrawOpaqueInterior(); | |
} | |
public override DrawNodeVisitor CreateVisitor() => new CompositeDrawNodeVisitor(); | |
} | |
public class CompositeDrawNodeVisitor : DrawNodeVisitor | |
{ | |
protected override void VisitDrawNode(DrawNode drawNode, List<IDrawNodeEvent> events) | |
{ | |
base.VisitDrawNode(drawNode, events); | |
CompositeDrawNode composite = (CompositeDrawNode)drawNode; | |
foreach (var child in composite.Children) | |
child.CreateVisitor().Visit(child, events); | |
} | |
} | |
public class BufferedDrawNode : DrawNode | |
{ | |
public readonly DrawNode Child; | |
public BufferedDrawNode(int index, DrawNode child) | |
: base(index) | |
{ | |
Child = child; | |
} | |
public void PopulateContents() | |
{ | |
Child.Draw(); | |
} | |
public override DrawNodeVisitor CreateVisitor() => new BufferedDrawNodeVisitor(); | |
} | |
public class BufferedDrawNodeVisitor : DrawNodeVisitor | |
{ | |
protected override void VisitDrawNode(DrawNode drawNode, List<IDrawNodeEvent> events) | |
{ | |
BufferedDrawNode buffered = (BufferedDrawNode)drawNode; | |
events.Add(new FrameBufferDrawEvent(buffered, n => ((BufferedDrawNode)n).PopulateContents())); | |
buffered.Child.CreateVisitor().Visit(buffered.Child, events); | |
base.VisitDrawNode(drawNode, events); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment