Skip to content

TES3 UI Example⚓︎

This example allows you to rename the object you are targetting. When the '/' key is pressed, a custom input window is opened.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
--[[
    Mod: TES3UI TextInput
    Author: Hrnchamd
]]--

local this = {}


function this.init()
    this.id_menu = tes3ui.registerID("example:MenuTextInput")
    this.id_input = tes3ui.registerID("example:MenuTextInput_Text")
    this.id_ok = tes3ui.registerID("example:MenuTextInput_Ok")
    this.id_cancel = tes3ui.registerID("example:MenuTextInput_Cancel")
end


-- Create window and layout. Called by onCommand.
function this.createWindow()
    -- Return if window is already open
    if (tes3ui.findMenu(this.id_menu) ~= nil) then
        return
    end

    -- Create window and frame
    local menu = tes3ui.createMenu{ id = this.id_menu, fixedFrame = true }

    -- To avoid low contrast, text input windows should not use menu transparency settings
    menu.alpha = 1.0

    -- Create layout
    local input_label = menu:createLabel{ text = "Rename your item" }
    input_label.borderBottom = 5

    local input_block = menu:createBlock{}
    input_block.width = 300
    input_block.autoHeight = true
    input_block.childAlignX = 0.5  -- centre content alignment

    local border = input_block:createThinBorder{}
    border.width = 300
    border.height = 30
    border.childAlignX = 0.5
    border.childAlignY = 0.5

    local input = border:createTextInput{ id = this.id_input }
    input.text = this.item.name  -- initial text
    input.borderLeft = 5
    input.borderRight = 5
    input.widget.lengthLimit = 31  -- TextInput custom properties
    input.widget.eraseOnFirstKey = true

    local button_block = menu:createBlock{}
    button_block.widthProportional = 1.0  -- width is 100% parent width
    button_block.autoHeight = true
    button_block.childAlignX = 1.0  -- right content alignment

    local button_cancel = button_block:createButton{ id = this.id_cancel, text = tes3.findGMST("sCancel").value }
    local button_ok = button_block:createButton{ id = this.id_ok, text = tes3.findGMST("sOK").value }

    -- Events
    button_cancel:register(tes3.uiEvent.mouseClick, this.onCancel)
    menu:register(tes3.uiEvent.keyEnter, this.onOK) -- only works when text input is not captured
    input:register(tes3.uiEvent.keyEnter, this.onOK)
    button_ok:register(tes3.uiEvent.mouseClick, this.onOK)

    -- Final setup
    menu:updateLayout()
    tes3ui.enterMenuMode(this.id_menu)
    tes3ui.acquireTextInput(input) -- automatically reset when menu is closed
end


-- OK button callback.
function this.onOK(e)
    local menu = tes3ui.findMenu(this.id_menu)

    if (menu) then
        -- Copy text *before* the menu is destroyed
        local name = menu:findChild(this.id_input).text

        tes3ui.leaveMenuMode()
        menu:destroy()

        tes3.messageBox{ message = this.item.name .. " renamed to " .. name }
        this.item.name = name
    end
end

-- Cancel button callback.
function this.onCancel(e)
    local menu = tes3ui.findMenu(this.id_menu)

    if (menu) then
        tes3ui.leaveMenuMode()
        menu:destroy()
    end
end

-- Keydown callback.
function this.onCommand(e)
    local t = tes3.getPlayerTarget()
    if (t) then
        t = t.object.baseObject or t.object -- Select actor base object

        if (t.name) then
            this.item = t
            this.createWindow()
        end
    end
end

event.register(tes3.event.initialized, this.init)
event.register(tes3.event.keyDown, this.onCommand, { filter = tes3.scanCode["/"] }) -- "/" key