1use core::fmt::Write;
2
3use taffy::{NodeId, TraversePartialTree};
4
5use bevy_ecs::prelude::Entity;
6use bevy_platform::collections::HashMap;
7
8use crate::layout::ui_surface::UiSurface;
9
10pub fn print_ui_layout_tree(ui_surface: &UiSurface) {
12 let taffy_to_entity: HashMap<NodeId, Entity> = ui_surface
13 .entity_to_taffy
14 .iter()
15 .map(|(entity, node)| (node.id, *entity))
16 .collect();
17 for (&entity, &viewport_node) in &ui_surface.root_entity_to_viewport_node {
18 let mut out = String::new();
19 print_node(
20 ui_surface,
21 &taffy_to_entity,
22 entity,
23 viewport_node,
24 false,
25 String::new(),
26 &mut out,
27 );
28
29 tracing::info!("Layout tree for camera entity: {entity}\n{out}");
30 }
31}
32
33fn print_node(
35 ui_surface: &UiSurface,
36 taffy_to_entity: &HashMap<NodeId, Entity>,
37 entity: Entity,
38 node: NodeId,
39 has_sibling: bool,
40 lines_string: String,
41 acc: &mut String,
42) {
43 let tree = &ui_surface.taffy;
44 let layout = tree.layout(node).unwrap();
45 let style = tree.style(node).unwrap();
46
47 let num_children = tree.child_count(node);
48
49 let display_variant = match (num_children, style.display) {
50 (_, taffy::style::Display::None) => "NONE",
51 (0, _) => "LEAF",
52 (_, taffy::style::Display::Flex) => "FLEX",
53 (_, taffy::style::Display::Grid) => "GRID",
54 (_, taffy::style::Display::Block) => "BLOCK",
55 };
56
57 let fork_string = if has_sibling {
58 "├── "
59 } else {
60 "└── "
61 };
62 writeln!(
63 acc,
64 "{lines}{fork} {display} [x: {x:<4} y: {y:<4} width: {width:<4} height: {height:<4}] ({entity}) {measured}",
65 lines = lines_string,
66 fork = fork_string,
67 display = display_variant,
68 x = layout.location.x,
69 y = layout.location.y,
70 width = layout.size.width,
71 height = layout.size.height,
72 measured = if tree.get_node_context(node).is_some() { "measured" } else { "" }
73 ).ok();
74 let bar = if has_sibling { "│ " } else { " " };
75 let new_string = lines_string + bar;
76
77 for (index, child_node) in tree.children(node).unwrap().iter().enumerate() {
79 let has_sibling = index < num_children - 1;
80 let child_entity = taffy_to_entity.get(child_node).unwrap();
81 print_node(
82 ui_surface,
83 taffy_to_entity,
84 *child_entity,
85 *child_node,
86 has_sibling,
87 new_string.clone(),
88 acc,
89 );
90 }
91}