mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-29 11:26:37 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			172 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| User interface reference
 | |
| ========================
 | |
| 
 | |
| .. toctree::
 | |
|     :hidden:
 | |
| 
 | |
|     widgets/widget
 | |
| 
 | |
| Layouts
 | |
| -------
 | |
| 
 | |
| Every widget is defined by a layout, which is a Lua table with the following fields (all of them are optional):
 | |
| 
 | |
| 1. `type`: One of the available widget types from `openmw.ui.TYPE`.
 | |
| 2. | `props`: A Lua table, containing all the properties values.
 | |
|    | Properties define most of the information about the widget: its position, data it displays, etc.
 | |
|    | See the widget pages (table below) for details on specific properties.
 | |
|    | Properties of the basic Widget are inherited by all the other widgets.
 | |
| 3. | `events`: A Lua table, containing `openmw.async.callback` values, which trigger on various interactions with the widget.
 | |
|    | See the Widget pages for details on specific events.
 | |
|    | Events of the basic Widget are inherited by all the other widgets.
 | |
| 4. `content`: a Content (`openmw.ui.content`), which contains layouts for the children of this widget.
 | |
| 5. | `name`: an arbitrary string, the only limitatiion is it being unique within a `Content`.
 | |
|    | Helpful for navigatilng through the layouts.
 | |
| 6. `layer`: only applies for the root widget. 
 | |
| 
 | |
| Layers
 | |
| ------
 | |
| Layers control how widgets overlap - layers with higher indexes cover render over layers with lower indexes.
 | |
| Widgets within the same layer which were added later overlap the ones created earlier.
 | |
| A layer can also be set as non-interactive, which prevents all mouse interactions with the widgets in that layer.
 | |
| 
 | |
| .. TODO: Move this list when layers are de-hardcoded
 | |
| 
 | |
| Pre-defined OpenMW layers:
 | |
| 
 | |
| 1. `HUD` interactive
 | |
| 2. `Windows` interactive
 | |
| 3. `Notification` non-interactive
 | |
| 4. `MessageBox` interactive
 | |
| 
 | |
| Elements
 | |
| --------
 | |
| 
 | |
| Element is the root widget of a layout.
 | |
| It is an independent part of the UI, connected only to a specific layer, but not any other layouts.
 | |
| Creating or destroying an element also creates/destroys all of its children.
 | |
| 
 | |
| Content
 | |
| -------
 | |
| 
 | |
| A container holding all the widget's children. It has a few important differences from a Lua table:
 | |
| 
 | |
| 1. All the keys are integers, i. e. it is an "array"
 | |
| 2. Holes are not allowed. At any point all keys from `1` to the highest `n` must contain a value.
 | |
| 3. | You can access the values by their `name` field as a `Content` key.
 | |
|    | While there is nothing preventing you from changing the `name` of a table inside a content, it is not supported, and will lead to undefined behaviour.
 | |
|    | If you have to change the name, assign a new table to the index instead.
 | |
| 
 | |
| .. TODO: Talk about skins/templates here when they are ready
 | |
| 
 | |
| Events
 | |
| ------
 | |
| 
 | |
| | A table mapping event names to `openmw.async.callback` s.
 | |
| | When an event triggers, the callback is called with two arguments:
 | |
|    an event-specific value, and that widget's layout table.
 | |
| | See the Widget type pages for information on what events exist, and which first argument they pass. 
 | |
| 
 | |
| Widget types
 | |
| ------------
 | |
| 
 | |
| .. list-table::
 | |
|    :widths: 30 70
 | |
| 
 | |
|    * - :ref:`Widget`
 | |
|      - Base widget type, all the other widget inherit its properties and events.
 | |
|    * - `Text`
 | |
|      - Displays text.
 | |
|    * - EditText
 | |
|      - Accepts text input from the user.
 | |
|    * - Window
 | |
|      - Can be moved and resized by the user.
 | |
| 
 | |
| Example
 | |
| -------
 | |
| 
 | |
| *scripts/requirePassword.lua*
 | |
| 
 | |
| .. code-block:: Lua
 | |
| 
 | |
|    local core = require('openmw.core')
 | |
|    local async = require('openmw.async')
 | |
|    local ui = require('openmw.ui')
 | |
|    local v2 = require('openmw.util').vector2
 | |
| 
 | |
|    local layout = {
 | |
|       layers = 'Windows',
 | |
|       type = ui.TYPE.Window,
 | |
|       skin = 'MW_Window', -- TODO: replace all skins here when they are properly implemented
 | |
|       props = {
 | |
|          size = v2(200, 250),
 | |
|          -- put the window in the middle of the screen
 | |
|          relativePosition = v2(0.5, 0.5),
 | |
|          anchor = v2(0.5, 0.5),
 | |
|       },
 | |
|       content = ui.content {
 | |
|          {
 | |
|             type = ui.TYPE.Text,
 | |
|             skin = 'SandText',
 | |
|             props = {
 | |
|                caption = 'Input password',
 | |
|                relativePosition = v2(0.5, 0),
 | |
|                anchor = v2(0.5, 0),
 | |
|             },
 | |
|          },
 | |
|          {
 | |
|             name = 'input',
 | |
|             type = ui.TYPE.TextEdit,
 | |
|             skin = "MW_TextEdit",
 | |
|             props = {
 | |
|                caption = '',
 | |
|                relativePosition = v2(0.5, 0.5),
 | |
|                anchor = v2(0.5, 0.5),
 | |
|                size = v2(125, 50),
 | |
|             },
 | |
|             events = {}
 | |
|          },
 | |
|          {
 | |
|             name = 'submit',
 | |
|             type = ui.TYPE.Text, -- TODO: replace with button when implemented
 | |
|             skin = "MW_Button",
 | |
|             props = {
 | |
|                caption = 'Submit',
 | |
|                -- position at the bottom
 | |
|                relativePosition = v2(0.5, 1.0),
 | |
|                anchor = v2(0.5, 1.0),
 | |
|                autoSize = false,
 | |
|                size = v2(75, 50),
 | |
|             },
 | |
|             events = {},
 | |
|          },
 | |
|       },
 | |
|    }
 | |
| 
 | |
|    local element = nil
 | |
| 
 | |
|    local input = layout.content.input
 | |
|    -- TODO: replace with a better event when TextEdit is finished
 | |
|    input.events.textInput = async:callback(function(text)
 | |
|       input.props.caption = input.props.caption .. text
 | |
|    end)
 | |
| 
 | |
|    local submit = layout.content.submit
 | |
|    submit.events.mouseClick = async:callback(function()
 | |
|       if input.props.caption == 'very secret password' then
 | |
|          if element then
 | |
|             element:destroy()
 | |
|          end
 | |
|       else
 | |
|          print('wrong password', input.props.caption)
 | |
|          core.quit()
 | |
|       end
 | |
|    end)
 | |
| 
 | |
|    element = ui.create(layout)
 | |
| 
 | |
| *requirePassword.omwscripts*
 | |
| 
 | |
| ::
 | |
| 
 | |
|   PLAYER: scripts/requirePassword.lua
 |