> For the complete documentation index, see [llms.txt](https://wiki.redmodding.org/scripting-cyberpunk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.redmodding.org/scripting-cyberpunk/scripting/game-systems/ui-scripting/logging-widget-trees.md).

# Logging Widget Trees

## Summary

**Published**: Mar 31 2024 by [mana vortex](mailto:undefined)\
**Last documented update**: Aug 20 2026 by [nolvalir](mailto:undefined)

This page will tell you how to log widget trees and layer trees.

{% hint style="info" %}
This requires [Codeware](/scripting-cyberpunk/introduction/tools-and-frameworks/codeware.md)
{% endhint %}

## Logging layer trees

You can find a list of existing UI layers on [UI Scripting](/scripting-cyberpunk/scripting/game-systems/ui-scripting.md) -> [UI Scripting](/scripting-cyberpunk/scripting/game-systems/ui-scripting.md#inksystemlayers).

To traverse a layer's children, you first need to get the corresponding layer's virtual window:

{% tabs %}
{% tab title="Redscript" %}

```swift
public static func PrintLayerHierarchy(layerName: CName) {
  let window = GameInstance.GetInkSystem().GetLayer(layerName).GetVirtualWindow();
  let rootWidget = window.GetWidgetByPathName(n"Root") as inkCanvas;

  // The function LogWidgetTree is defined below
  LogWidgetTree(rootWidget);
}

PrintLayerHierarchy(n"inkHUDLayer");
```

{% endtab %}

{% tab title="Lua" %}

```lua
function PrintLayerHierarchy(layerName)
  local window = GameInstance.GetInkSystem():GetLayer(layerName):GetVirtualWindow()
  local rootWidget = window:GetWidgetByPathName("Root")

  -- The function LogWidgetTree is defined below
  LogWidgetTree(rootWidget, false, "")
end

PrintLayerHierarchy("inkHUDLayer")
```

{% endtab %}
{% endtabs %}

### Logging Widget Trees

{% hint style="info" %}
Big thanks to **Rayshader** for walking me through this with the patience of a saint!
{% endhint %}

{% tabs %}
{% tab title="Redscript" %}

```swift
public static func LogWidgetTree(widget: wref<inkCompoundWidget>, opt props: Bool, opt indent: String) {
  let i = 0;

  if StrLen(indent) == 0 {
    FTLog(s"\(widget.GetName()) - \(widget.GetClassName())");
  }

  while i < widget.GetNumChildren() {
    let child: wref<inkWidget> = widget.GetWidget(i);
    let compChild = child as inkCompoundWidget;

    FTLog(s"\(indent)|-- \(child.GetName()) - \(child.GetClassName())");

    if props {
        let anchor = child.GetAnchor();
        let size = child.GetSize();
        let scale = child.GetScale();

        FTLog(s"\(indent){");
        FTLog(s"\(indent)  anchor: inkEAnchor.\(anchor)");
        FTLog(s"\(indent)  size: (\(size.X), \(size.Y))");
        FTLog(s"\(indent)  scale: (\(scale.X), \(scale.Y))");
        let wText = child as inkText;

        if IsDefined(wText) {
          FTLog(s"\(indent)  text: \"\(wText.GetText())\"");
          FTLog(s"\(indent)  fontSize: \"\(wText.GetFontSize())\"");
        }
        FTLog(s"\(indent)}");
      }

      if IsDefined(compChild) {
        LogWidgetTree(compChild, props, s"\(indent)    ");
      }

      i += 1;
    }
  }
```

{% endtab %}

{% tab title="Lua" %}

```lua
function LogWidgetTree(widget, props, indent)
  local i = 0

  if indent == 0 then
    print(NameToString(widget:GetName()) .. " - " .. NameToString(widget:GetClassName()))
  end

  while i < widget:GetNumChildren() do
    local child = widget:GetWidget(i)

    print(indent .. "|-- " .. NameToString(child:GetName()) .. " - " .. NameToString(child:GetClassName()))

    if props then
      local anchor = child:GetAnchor()
      local size = child:GetSize()
      local scale = child:GetScale()

      print(indent .. "{")
      print(indent .. "  anchor: inkEAnchor." .. anchor.value)
      print(indent .. "  size: (" .. tostring(size.X) .. ", " .. tostring(size.Y) .. ")")
      print(indent .. "  scale: (" .. tostring(scale.X) .. ", " .. tostring(scale.Y) .. ")")

      if child:IsA("inkTextWidget") then
        print(indent .. "  text: \"" .. child:GetText() .. "\"")
        print(indent .. "  fontSize: \"" .. tostring(child:GetFontSize()) .. "\"")
      end

      print(indent .. "}")
    end

    if child:IsA("inkCompoundWidget") then
      LogWidgetTree(child, props, indent .. "    ")
    end

    i = i + 1
  end
end
```

{% endtab %}
{% endtabs %}
