Difference between revisions of "LuaAPI/gui/example"

From The Battle for Wesnoth Wiki
< LuaAPI‎ | gui
(Example of creating a custom GUI2 dialog from Lua; probably needs some work but is basically complete and functional)
 
(The Implementation: Update to synchronize the dialog result)
Line 218: Line 218:
 
   end
 
   end
 
   local dialog_wml = wml.load "character_select.cfg"
 
   local dialog_wml = wml.load "character_select.cfg"
   if -1 == gui.show_dialog(wml.get_child(dialog_wml, 'resolution'), pre_show, post_show) then
+
   wml.variables.selected_character = wesnoth.sync.evaluate_single(function()
    wml.variables.selected_character = characters[selection].id
+
    local result = false
  else
+
    if -1 == gui.show_dialog(wml.get_child(dialog_wml, 'resolution'), pre_show, post_show) then
     wml.variables.selected_character = nil
+
      result = characters[selection].id
   end
+
    end
 +
     return {selected = result}
 +
   end).selected
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>

Revision as of 23:38, 5 July 2021

Using the gui.show_dialog function, you can create pretty much any custom dialog you want using the standard GUI2 markup that constructs most of Wesnoth's built-in UIs. This page is dedicated to a fully-working example that demonstrates some of the intricacies of the system.

We're going to create a character selection dialog, similar to the tutorial dialog, but with more than two choices. Since there will be several choices, we'll use a listbox. In order to be as user-friendly as possible, we'll register an ActionWML tag that calls the dialog and stores an ID in a variable.

The Dialog WML

First, you need to write your GUI2 WML. We recommend putting the WML in a .cfg file, in a [resolution] tag. Though the resolution tag is not required, using it means you could have multiple versions of the dialog in the same file (for example, a different layout for small screens) and choose between them, if the API is updated to support this in the future (which is likely).

The remainder of this example will assume this code is pasted into a file called "Your_Addon/character_select.cfg".

#textdomain wesnoth-gui-example
{gui/macros} # Built-in macros that are useful for GUI WML; not used in this example 
[resolution]
  definition = "default"
  automatic_placement = true
  vertical_placement = "center"
  horizontal_placement = "center"
  maximum_width = 800
  maximum_height = 600
  [linked_group]
    id = "image"
    fixed_width = true
  [/linked_group]
  [linked_group]
    id = "item"
    fixed_width = true
  [/linked_group]
  [tooltip]
    id = "tooltip"
  [/tooltip]
  [helptip]
    id = "tooltip"
  [/helptip]
  [grid]
    [row]
      grow_factor = 0
        [column]
          grow_factor = 1
          border = "all"
          border_size = 5
          horizontal_alignment = "left"
          [label]
            id =  "title"
            definition = "title"
          [/label]
        [/column]
      [/row]
      [row]
        grow_factor = 0
        [column]
          grow_factor = 1
          border = "all"
          border_size = 5
          horizontal_alignment = "left"
          [scroll_label]
            id = "message"
            definition = "default"
          [/scroll_label]
        [/column]
      [/row]
      [row]
        grow_factor = 1
        [column]
          grow_factor = 1
          horizontal_grow = true
          vertical_grow = true
          border = "all"
          border_size = 5
          [listbox]
            id = "characters"
            definition = "default"
            [list_definition]
              [row]
                [column]
                  vertical_grow = true
                  horizontal_grow = true
                  [toggle_panel]
                    definition = "default"
                    return_value_id = "ok"
                    [grid]
                      [row]
                          [column]
                            grow_factor = 0
                            horizontal_grow = false
                            border = "all"
                            border_size = 5
                            [image]
                              id = "image"
                              definition = "default"
                              linked_group = "image"
                            [/image]
                          [/column]
                          [column]
                            grow_factor = 0
                            horizontal_grow = false
                            border = "all"
                            border_size = 5
                            [label]
                              id = "item"
                              definition = "default"
                              linked_group = "item"
                            [/label]
                          [/column]
                          [column]
                            grow_factor = 1
                            horizontal_grow = true
                            border = "all"
                            border_size = 5
                            [label]
                              id = "description"
                              definition = "default"
                              linked_group = "item"
                            [/label]
                          [/column]
                      [/row]
                    [/grid]
                  [/toggle_panel]
                [/column]
              [/row]
            [/list_definition]
          [/listbox]
        [/column]
      [/row]
      [row]
        grow_factor = 0
        [column]
          horizontal_alignment = "right"
          [grid]
            [row]
              grow_factor = 0
              [column]
                border = "all"
                border_size = 5
                horizontal_alignment = "right"
                [button]
                  id = "ok"
                  definition = "default"
                  label = _ "OK"
                [/button]
              [/column]
              [column]
                border = "all"
                border_size = 5
                horizontal_alignment = "right"
                [button]
                  id = "cancel"
                  definition = "default"
                  label = _ "Cancel"
                [/button]
              [/column]
            [/row]
          [/grid]
        [/column]
      [/row]
    [/grid]
[/resolution]

The Implementation

local _ = wesnoth.textdomain "wesnoth-gui-example"
-- Some sample data for the dialog
local characters = {
  {
    id = "konrad",
    name = _ "Konrad",
    image = "units/konrad-fighter.png",
    description = _ "A bright young prince, skilled with the sword!"
  },
  {
    id = "lisar",
    name = _ "Li'sar",
    image = "units/human-princess.png~RC(magenta>red)",
    description = _ "A bright young princess, skilled with the sword!"
  },
  {
    id = "delfador",
    name = _ "Delfador",
    image = "units/human-magi/elder-mage.png~RC(magenta>red)",
    description = _ "A jaded old mage, wields powerful lightning magic!"
  },
  {
    id = "kalenz",
    name = _ "Kalenz",
    image = "units/elves-wood/high-lord.png~RC(magenta>green)",
    description = _ "A jaded old mage, wields powerful lightning magic!"
  },
  -- Add more characters here, if you want!
}
function wesnoth.wml_actions.select_character(cfg)
  -- If you uncomment this line you can specify the character options directly in the WML tag.
  -- Just add a [character] subtag for each character with id, name, image, and description.
  --local characters = wml.child_array(cfg, 'character')
  local selection = 1
  function pre_show(self)
    -- Set the title and text.
    -- Normally you'd do this in the WML if they're static text, but for this example we show how you can update them dynamically if needed.
    self.title.label = _ "Select a Character"
    self.message.label = _ "Before you get started, you need to select a character."
    -- Look up the list box by its ID
    local listbox = self.characters
    for i, character in ipairs(characters) do
      -- Add a new blank item to the list
      local new_item = listbox:add_item()
      -- The new item has "image" and "item" subwidgets,
      -- so set their values appropriately
      new_item.image.label = character.image
      new_item.item.label = character.name
      new_item.description.label = character.description
    end
    listbox.selected_index = selection
  end
  function post_show(self)
    selection = self.characters.selected_index
  end
  local dialog_wml = wml.load "character_select.cfg"
  wml.variables.selected_character = wesnoth.sync.evaluate_single(function()
    local result = false
    if -1 == gui.show_dialog(wml.get_child(dialog_wml, 'resolution'), pre_show, post_show) then
      result = characters[selection].id
    end
    return {selected = result}
  end).selected
end