> 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/guide-to-ui-basics/ui-basics-part-1-accessing-ink-widgets.md).

# UI Basics: Part 1 - Accessing Ink Widgets

How to get a reference to an ink widget

{% hint style="info" %}
This is part 1 of the guide for UI scripting in Cyberpunk, for the other parts in the guide, look here:

* Overview: [UI Scripting](/scripting-cyberpunk/scripting/game-systems/ui-scripting.md)
* Part 1: [UI Basics: Part 1 - Accessing Ink Widgets](/scripting-cyberpunk/scripting/game-systems/ui-scripting/guide-to-ui-basics/ui-basics-part-1-accessing-ink-widgets.md)
* Part 2: [UI Basics: Part 2 - Modifying Ink Widgets](/scripting-cyberpunk/scripting/game-systems/ui-scripting/guide-to-ui-basics/ui-basics-part-2-modifying-ink-widgets.md)
* Part 3: [UI Basics: Part 3 - Adding Ink Widgets](/scripting-cyberpunk/scripting/game-systems/ui-scripting/guide-to-ui-basics/ui-basics-part-3-adding-ink-widgets.md)
* Part 4: [UI Basics: Part 4 - Advanced Example](/scripting-cyberpunk/scripting/game-systems/ui-scripting/guide-to-ui-basics/ui-basics-part-4-advanced-example.md)
  {% endhint %}

Getting a reference to an ink widget depends on the widget's context (where it's from) and where you want to get the reference. You can usually find the [ink controller](/scripting-cyberpunk/scripting/game-systems/ui-scripting/ink-controllers.md#finding-an-ink-controller) that's responsible for the widget and hook into its [lifecycle events](/scripting-cyberpunk/scripting/game-systems/ui-scripting/ink-controllers.md#lifecycle-events) to get a reference to your desired widget.

If you have [Codeware](/scripting-cyberpunk/introduction/tools-and-frameworks/codeware.md) installed, the game's ink system is available with `GameInstance.GetInkSystem()`, which allows you to get the reference to your desired widget on demand at any point in your code (assuming the ink system is available).

## Hooking Into An Ink Controller

When hooking into an ink controller through its [lifecycle events](/scripting-cyberpunk/scripting/game-systems/ui-scripting/ink-controllers.md#lifecycle-events) or other methods, using `inkController#GetRootCompoundWidget()` if it's a container or `inkController#GetRootWidget` if it's not a container will give you the widget the ink controller is assigned to, *not* the root widget of the UI tree as a whole.

If the ink controller is attached to a [container](/scripting-cyberpunk/scripting/game-systems/ui-scripting/ink-widgets.md#containers), using `GetRootCompoundWidget` will give you the reference to the root container, which you can then use the respective methods, notably [`inkCompoundWidget#GetWidgetByPathName`](https://nativedb.red4ext.com/inkCompoundWidget#GetWidgetByPathName) that lets you traverse the tree to pick a child from any depth of the root. Additionally, ink controllers may also have some [properties that references commonly accessed ink widgets](/scripting-cyberpunk/scripting/game-systems/ui-scripting/ink-widgets.md#ink-references) from the UI tree within the controller, which you can use as well.

An example is the text representing how much money you have in the hub menu. By using Ink Inspector and traversing the tree, we can find that [`SubMenuPanelLogicController`](https://nativedb.red4ext.com/SubMenuPanelLogicController) is the controller that's responsible for this widget, and here's how we can get a reference to it.

### Looking For The Widget

Since the controller is attached to a container, so we can use [`inkWidgetLogicController#GetRootCompoundWidget`](https://nativedb.red4ext.com/inkWidgetLogicController#GetRootCompoundWidget) to get the reference to the container, then get access to the text widget for the text.

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

```swift
@wrapMethod(SubMenuPanelLogicController)
protected cb func OnInitialize() -> Bool {
  wrappedMethod();

  let root = this.GetRootCompoundWidget();
  let text = root.GetWidgetByPathName(n"topPanels/holder/right_holder/credit_holder/value") as inkText; // https://nativedb.red4ext.com/c/2864209969622273
}
```

{% endtab %}

{% tab title="Lua" %}

```lua
registerForEvent('onInit', function()
  ---@param this MenuHubGameController
  ObserveAfter("SubMenuPanelLogicController", "OnInitialize", function(this)
    local root = this:GetRootCompoundWidget()
    local text = root:GetWidgetByPathName("topPanels/holder/right_holder/credit_holder/value") -- https://nativedb.red4ext.com/c/2864209969622273
  end)
end)
```

{% endtab %}
{% endtabs %}

### Using Property References

The controller also has a property that references the text widget for the currency value, so you don't have to manually get one with `GetWidgetByPathName`. In our case, the controller's property that references this is `m_currencyValue`:

```swift
private edit let m_currencyValue: inkTextRef;
```

{% hint style="info" %}
Look at your controller in [NativeDB](/scripting-cyberpunk/introduction/resources.md#references-and-resources) or the source code in the [de-compiled scripts](/scripting-cyberpunk/introduction/resources.md#references-and-resources) to see if it has any ink widget property references.
{% endhint %}

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

```swift
@wrapMethod(SubMenuPanelLogicController)
protected cb func OnInitialize() -> Bool {
  wrappedMethod();

  // do something with `this.m_currencyValue` - https://nativedb.red4ext.com/s/7852530694133962
}
```

{% endtab %}

{% tab title="Lua" %}

```lua
registerForEvent('onInit', function()
  ---@param this MenuHubGameController
  ObserveAfter("SubMenuPanelLogicController", "OnInitialize", function(this)
    -- do something with `this.currencyValue` - https://nativedb.red4ext.com/s/7852530694133962
  end)
end)
```

{% hint style="info" %}
For Lua, don't forget that the `m_` attribute is removed from property names.
{% endhint %}
{% endtab %}
{% endtabs %}

## Ink Layers

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

With [Codeware](/scripting-cyberpunk/introduction/tools-and-frameworks/codeware.md), we have access to the game's ink system with `GameInstance.GetInkSystem()`, this exposes the various [ink layers](https://wiki.redmodding.org/scripting-cyberpunk/scripting/game-systems/ui-scripting/guide-to-ui-basics/pages/k81UnWc76dSM5ndnBewU#ink-layers-as-of-2.12_a) in the game which sub-sequentially gives access to all spawned widgets within the various layers.

### Querying Ink Layers

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

```swift
private static func DumpInkHudLayers() {
  let inkSystem = GameInstance.GetInkSystem();
  let layers = inkSystem.GetLayers();

  for layer in layers {
    FTLog(s"UI Layer: \(layer.GetLayerName()) \(layer.GetGameController().GetClassName())");
  }
}
```

{% endtab %}

{% tab title="Lua" %}

```lua
function DumpInkHudLayers()
  local layers = GameInstance.GetInkSystem():GetLayers()

  for _, layer in ipairs(layers) do
    local layerName = NameToString(layer:GetLayerName())
    local controller = layer:GetGameController()
    local controllerName

    if controller == nil then
      controllerName = "None"
    else
      controllerName = NameToString(controller:GetClassName())
    end

    print("UI Layer: " .. layerName .. " " .. controllerName)
  end
end

DumpInkHudLayers()
```

{% endtab %}
{% endtabs %}

### Accessing Layers

You can access any existing layer via the game instance's InkSystem. Simply pass the layer's name as `CName` (for a list of existing options, see the table below):

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

```swift
let hudLayer = GameInstance.GetInkSystem().GetLayer(n"inkHUDLayer");
// ...
```

{% endtab %}

{% tab title="Lua" %}

```lua
local hudLayer = GameInstance.GetInkSystem():GetLayer("inkHUDLayer")
-- ...
```

{% endtab %}
{% endtabs %}

### Accessing Widgets On Demand

At any point in the game, as long as the ink system is available, you can use `GetInkSystem` to get a reference to a widget on demand.

{% hint style="info" %}
To find functions for traversing widget trees, check the [nativeDB page for inkCompoundWidget](https://nativedb.red4ext.com/inkCompoundWidget).
{% endhint %}

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

```swift
let window = GameInstance.GetInkSystem().GetLayer(n"inkHUDLayer").GetVirtualWindow();
let root = window.GetWidgetByPathName(n"Root") as inkCanvas;

// Those two are the same:
let hudMiddle1 = root.GetWidgetByPathName(n"HUDMiddleWidget");
let hudMiddle2 = window.GetWidgetByPathName(n"Root/HUDMiddleWidget");
```

{% endtab %}

{% tab title="Lua" %}

```lua
local window = GameInstance.GetInkSystem():GetLayer("inkHUDLayer"):GetVirtualWindow()
local root = window:GetWidgetByPathName("Root")

-- Those two are the same:
local hudMiddle1 = root:GetWidgetByPathName("HUDMiddleWidget")
local hudMiddle2 = window:GetWidgetByPathName("Root/HUDMiddleWidget")
```

{% endtab %}
{% endtabs %}
