@@ -67,6 +67,9 @@ public class ClayContext : IDisposable
6767 public uint Generation ;
6868 public float DeltaTime ;
6969 public bool DebugModeEnabled ;
70+ // Debug overlay: outline the elements under the pointer (topmost lime,
71+ // occluded-beneath red). Emitted by GeneratePointerHighlightCommands.
72+ public bool PointerHighlightEnabled ;
7073 public bool CullingDisabled ;
7174
7275 // Text measurement
@@ -236,9 +239,69 @@ public ReadOnlySpan<RenderCommand> EndLayout()
236239 CloseElement ( ) ;
237240 ComputeLayout ( ) ;
238241 GenerateRenderCommands ( ) ;
242+ GeneratePointerHighlightCommands ( ) ;
239243 return RenderCommands . AsReadOnlySpan ( ) ;
240244 }
241245
246+ // Debug overlay: frame the elements under the pointer. The topmost hit
247+ // (PointerOverIds[0]) is outlined lime; every element occluded beneath it
248+ // at the same point is outlined red. Appended after the normal commands so
249+ // the outlines paint on top. Pure bbox/z hit — the host's per-pixel
250+ // CustomHitTest is NOT applied here, so this shows Clay's own stacking pick.
251+ private void GeneratePointerHighlightCommands ( )
252+ {
253+ if ( ! PointerHighlightEnabled )
254+ return ;
255+
256+ // Gray frame around every element laid out this frame (Generation + 1
257+ // is this frame's stamp; the hash map keeps recycled entries from prior
258+ // frames). Emitted first so the lime/red pointer outlines paint over it.
259+ var gray = new Color ( 150 , 150 , 150 , 110 ) ;
260+ for ( int i = 0 ; i < LayoutElementsHashMapInternal . Length ; i ++ )
261+ {
262+ ref var item = ref LayoutElementsHashMapInternal [ i ] ;
263+ if ( item . Generation != Generation + 1 )
264+ continue ;
265+ RenderCommands . Add ( new RenderCommand
266+ {
267+ BoundingBox = item . BoundingBox ,
268+ CommandType = RenderCommandType . Border ,
269+ Id = item . ElementId . Id ,
270+ ZIndex = short . MaxValue ,
271+ Border = new BorderRenderData
272+ {
273+ Color = gray ,
274+ Width = BorderWidth . All ( 1 ) ,
275+ CornerRadius = default ,
276+ }
277+ } ) ;
278+ }
279+
280+ // Rebuild against the freshly computed layout (SetPointerState earlier
281+ // in the frame hit-tested the previous frame's tree).
282+ RebuildPointerOverIds ( PointerInfo . Position ) ;
283+
284+ var lime = new Color ( 0 , 255 , 0 , 255 ) ;
285+ var red = new Color ( 255 , 0 , 0 , 255 ) ;
286+
287+ for ( int i = 0 ; i < PointerOverIds . Length ; i ++ )
288+ {
289+ RenderCommands . Add ( new RenderCommand
290+ {
291+ BoundingBox = _pointerOverBoxes [ i ] ,
292+ CommandType = RenderCommandType . Border ,
293+ Id = PointerOverIds [ i ] . Id ,
294+ ZIndex = short . MaxValue ,
295+ Border = new BorderRenderData
296+ {
297+ Color = i == 0 ? lime : red ,
298+ Width = BorderWidth . All ( 2 ) ,
299+ CornerRadius = default ,
300+ }
301+ } ) ;
302+ }
303+ }
304+
242305 /// <summary>
243306 /// Opens a new element.
244307 /// </summary>
0 commit comments