A game framework written with osu! in mind.
at master 117 lines 4.4 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using osu.Framework.Graphics.OpenGL; 6using osu.Framework.Graphics.OpenGL.Vertices; 7using osu.Framework.Graphics.Primitives; 8 9namespace osu.Framework.Graphics 10{ 11 public abstract partial class Drawable 12 { 13 private class ProxyDrawable : Drawable 14 { 15 private readonly ulong[] drawNodeValidationIds = new ulong[GLWrapper.MAX_DRAW_NODES]; 16 private readonly DrawNode[] originalDrawNodes; 17 18 internal ProxyDrawable(Drawable original) 19 { 20 Original = original; 21 originalDrawNodes = (original as ProxyDrawable)?.originalDrawNodes ?? original.drawNodes; 22 23 original.LifetimeChanged += _ => LifetimeChanged?.Invoke(this); 24 } 25 26 internal override void ValidateProxyDrawNode(int treeIndex, ulong frame) 27 { 28 if (HasProxy) 29 { 30 // Proxy of a proxy - forward the next proxy 31 base.ValidateProxyDrawNode(treeIndex, frame); 32 return; 33 } 34 35 drawNodeValidationIds[treeIndex] = frame; 36 } 37 38 protected override DrawNode CreateDrawNode() => new ProxyDrawNode(this); 39 40 internal override DrawNode GenerateDrawNodeSubtree(ulong frame, int treeIndex, bool forceNewDrawNode) 41 { 42 var node = (ProxyDrawNode)base.GenerateDrawNodeSubtree(frame, treeIndex, forceNewDrawNode); 43 44 node.DrawNodeIndex = treeIndex; 45 node.FrameCount = frame; 46 47 return node; 48 } 49 50 internal sealed override Drawable Original { get; } 51 52 public override bool RemoveWhenNotAlive => Original.RemoveWhenNotAlive; 53 54 protected internal override bool ShouldBeAlive => Original.ShouldBeAlive; 55 56 public override double LifetimeStart => Original.LifetimeStart; 57 58 public override double LifetimeEnd => Original.LifetimeEnd; 59 60 // We do not want to receive updates. That is the business of the original drawable. 61 public override bool IsPresent => false; 62 63 public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) 64 { 65 if (Original.IsDisposed) 66 return false; 67 68 return Original.UpdateSubTreeMasking(this, maskingBounds); 69 } 70 71 private class ProxyDrawNode : DrawNode 72 { 73 /// <summary> 74 /// The index of the original draw node to draw. 75 /// </summary> 76 public int DrawNodeIndex; 77 78 /// <summary> 79 /// The current draw frame index. 80 /// If this differs from the frame index of the original draw node, the original drawable will have not been drawn this frame. 81 /// </summary> 82 public ulong FrameCount; 83 84 protected new ProxyDrawable Source => (ProxyDrawable)base.Source; 85 86 public ProxyDrawNode(ProxyDrawable proxyDrawable) 87 : base(proxyDrawable) 88 { 89 } 90 91 internal override void DrawOpaqueInteriorSubTree(DepthValue depthValue, Action<TexturedVertex2D> vertexAction) 92 => getCurrentFrameSource()?.DrawOpaqueInteriorSubTree(depthValue, vertexAction); 93 94 public override void Draw(Action<TexturedVertex2D> vertexAction) 95 => getCurrentFrameSource()?.Draw(vertexAction); 96 97 protected internal override bool CanDrawOpaqueInterior => getCurrentFrameSource()?.CanDrawOpaqueInterior ?? false; 98 99 private DrawNode getCurrentFrameSource() 100 { 101 var target = Source.originalDrawNodes[DrawNodeIndex]; 102 103 if (target == null) 104 return null; 105 106 if (Source.drawNodeValidationIds[DrawNodeIndex] != FrameCount) 107 return null; 108 109 if (target.IsDisposed) 110 return null; 111 112 return target; 113 } 114 } 115 } 116 } 117}