MWUI interface (resolve #6594)
Includes a mechanism for overriding templates, which supports dynamic changes to templates at any point during runtime.
Some templates include "legacy" MyGUI skins, and should be replaced when #6654 (closed) is implemented.
Some points which are still not clear to me:
- The template push/pop overloading methods assume all the passed templates are different tables, and that scripts only change the templates they've added themselves. The problem is that most of the time people will only slightly modify existing templates, and will want to make a copy of them, which is not trivial to do (even in the example below
deepCopydoesn't copyui.contents correctly. We should either provide a standarddeepCopyfunction, or come up with an easier way to do this. - Currently the UI package doesn't expose the resources, maybe it should. It's not clear to me if it's useful, as they can't be overridden this way anyway.
- push and pop are a bit clunky, as
popimplies it removes the top of the override stack, while it actually removes the template passed to it as an argument. I guess I should rename them toaddTemplateOverideandremoveTemplateOverride, but maybe anyone has other suggestions on how to handle the override list for each template key. - updateAll implementation is a bit iffy.
- Maybe this should be a package, rather than an interface.
Example of a script which allows to dynamically change the font size and borders on all UI elements.
local ui = require('openmw.ui')
local util = require('openmw.util')
local async = require('openmw.async')
local interfaces = require('openmw.interfaces')
local v2 = util.vector2
local mwUi = interfaces.MWUI
local textEditBoxOverride = ui.deepLayoutCopy(mwUi.templates.textEditBox)
mwUi:override('textEditBox', textEditBoxOverride)
local bordersOverride
local bordersToggle = true
local textProps = textEditBoxOverride.props
ui.create {
template = mwUi.templates.box,
type = ui.TYPE.Widget,
layer = 'Windows',
props = {
size = v2(700, 700),
relativePosition = v2(0.5, 0.5),
anchor = v2(0.5, 0.5),
},
content = ui.content {
{
type = ui.TYPE.TextEdit,
template = mwUi.templates.textEditBox,
props = {
relativePosition = v2(0, 0),
anchor = v2(0, 0),
relativeSize = v2(1, 0.5),
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas eu arcu odio. Maecenas luctus pellentesque ullamcorper. Duis ut laoreet erat. Mauris eros lacus, ullamcorper et interdum at, auctor ac ipsum. Nunc ac ante suscipit, ornare est sed, lacinia nibh. Sed at tempor tellus. Nam egestas vestibulum tortor sit amet finibus.",
wordWrap = true,
multiline = true,
},
events = {
mousePress = async:callback(function(e)
if e.button ~= 0 then
ui.updateAll()
return
end
ui.showMessage(("Toggled borders %s"):format(bordersToggle and 'yes' or 'no'))
if bordersToggle then
bordersOverride = mwUi:temporaryOverride('borders', {})
else
if bordersOverride then
bordersOverride()
end
end
bordersToggle = not bordersToggle
ui.updateAll()
end),
},
},
{
type = ui.TYPE.Widget,
template = mwUi.templates.borders,
props = {
relativePosition = v2(0.25, 0.75),
anchor = v2(0.5, 0.5),
size = v2(100, 60),
},
content = ui.content {
{
type = ui.TYPE.Text,
template = mwUi.templates.textNormal,
props = {
text = "Smaller",
relativePosition = v2(0.5, 0.5),
anchor = v2(0.5, 0.5),
},
events = {
mouseClick = async:callback(function()
textProps.textSize = textProps.textSize - 1
mwUi:override('textEditBox', textEditBoxOverride)
ui.showMessage(("Text size %i"):format(textProps.textSize))
ui.updateAll()
end),
},
}
},
},
{
type = ui.TYPE.Widget,
template = mwUi.templates.borders,
props = {
relativePosition = v2(0.5, 0.75),
anchor = v2(0.5, 0.5),
size = v2(100, 60),
},
content = ui.content {
{
type = ui.TYPE.Text,
template = mwUi.templates.textNormal,
props = {
text = "Bigger",
relativePosition = v2(0.5, 0.5),
anchor = v2(0.5, 0.5),
},
events = {
mouseClick = async:callback(function()
textProps.textSize = textProps.textSize + 1
mwUi:override('textEditBox', textEditBoxOverride)
ui.showMessage(("Text size %i"):format(textProps.textSize))
ui.updateAll()
end),
},
}
},
},
{
type = ui.TYPE.Widget,
template = mwUi.templates.borders,
props = {
relativePosition = v2(0.75, 0.75),
anchor = v2(0.5, 0.5),
size = v2(150, 60),
},
content = ui.content {
{
type = ui.TYPE.Text,
template = mwUi.templates.textNormal,
props = {
text = "Toggle Borders",
relativePosition = v2(0.5, 0.5),
anchor = v2(0.5, 0.5),
},
events = {
mouseClick = async:callback(function()
ui.showMessage(("Toggled borders %s"):format(bordersToggle and 'yes' or 'no'))
if bordersToggle then
bordersOverride = mwUi:temporaryOverride('borders', {})
else
if bordersOverride then
bordersOverride()
end
end
bordersToggle = not bordersToggle
ui.updateAll()
end),
},
}
},
},
}
}
Edited by uramer