mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
288 lines
9.7 KiB
Lua
288 lines
9.7 KiB
Lua
local core = require('openmw.core')
|
|
local ui = require('openmw.ui')
|
|
local async = require('openmw.async')
|
|
local util = require('openmw.util')
|
|
local I = require('openmw.interfaces')
|
|
|
|
local function applyDefaults(argument, defaults)
|
|
if not argument then return defaults end
|
|
if pairs(defaults) and pairs(argument) then
|
|
local result = {}
|
|
for k, v in pairs(defaults) do
|
|
result[k] = v
|
|
end
|
|
for k, v in pairs(argument) do
|
|
result[k] = v
|
|
end
|
|
return result
|
|
end
|
|
return argument
|
|
end
|
|
|
|
local function paddedBox(layout)
|
|
return {
|
|
template = I.MWUI.templates.box,
|
|
content = ui.content {
|
|
{
|
|
template = I.MWUI.templates.padding,
|
|
content = ui.content { layout },
|
|
},
|
|
}
|
|
}
|
|
end
|
|
|
|
local function disable(disabled, layout)
|
|
if disabled then
|
|
return {
|
|
template = I.MWUI.templates.disabled,
|
|
content = ui.content {
|
|
layout,
|
|
},
|
|
}
|
|
else
|
|
return layout
|
|
end
|
|
end
|
|
|
|
return function(registerRenderer)
|
|
do
|
|
local defaultArgument = {
|
|
disabled = false,
|
|
}
|
|
registerRenderer('textLine', function(value, set, argument)
|
|
argument = applyDefaults(argument, defaultArgument)
|
|
return disable(argument.disabled, paddedBox {
|
|
template = I.MWUI.templates.textEditLine,
|
|
props = {
|
|
text = tostring(value),
|
|
},
|
|
events = {
|
|
textChanged = async:callback(function(s) set(s) end),
|
|
},
|
|
})
|
|
end)
|
|
end
|
|
|
|
do
|
|
local defaultArgument = {
|
|
disabled = false,
|
|
l10n = 'Interface',
|
|
trueLabel = 'Yes',
|
|
falseLabel = 'No',
|
|
}
|
|
registerRenderer('checkbox', function(value, set, argument)
|
|
argument = applyDefaults(argument, defaultArgument)
|
|
local l10n = core.l10n(argument.l10n)
|
|
local box = paddedBox {
|
|
template = I.MWUI.templates.padding,
|
|
content = ui.content {
|
|
{
|
|
template = I.MWUI.templates.textNormal,
|
|
props = {
|
|
text = l10n(value and argument.trueLabel or argument.falseLabel)
|
|
},
|
|
},
|
|
},
|
|
}
|
|
box.events = {
|
|
mouseClick = async:callback(function() set(not value) end)
|
|
}
|
|
return disable(argument.disabled, box)
|
|
end)
|
|
end
|
|
|
|
do
|
|
local function validateNumber(text, argument)
|
|
local number = tonumber(text)
|
|
if not number then return end
|
|
if argument.min and number < argument.min then return end
|
|
if argument.max and number > argument.max then return end
|
|
if argument.integer and math.floor(number) ~= number then return end
|
|
return number
|
|
end
|
|
local defaultArgument = {
|
|
disabled = false,
|
|
integer = false,
|
|
min = nil,
|
|
max = nil,
|
|
}
|
|
registerRenderer('number', function(value, set, argument)
|
|
argument = applyDefaults(argument, defaultArgument)
|
|
local lastInput = nil
|
|
return disable(argument.disabled, paddedBox {
|
|
template = I.MWUI.templates.textEditLine,
|
|
props = {
|
|
text = tostring(value),
|
|
size = util.vector2(80, 0),
|
|
},
|
|
events = {
|
|
textChanged = async:callback(function(text)
|
|
lastInput = text
|
|
end),
|
|
focusLoss = async:callback(function()
|
|
if not lastInput then return end
|
|
local number = validateNumber(lastInput, argument)
|
|
if not number then
|
|
set(value)
|
|
end
|
|
if number and number ~= value then
|
|
set(number)
|
|
end
|
|
end),
|
|
},
|
|
})
|
|
end)
|
|
end
|
|
|
|
do
|
|
local defaultArgument = {
|
|
disabled = false,
|
|
l10n = nil,
|
|
items = {},
|
|
}
|
|
local leftArrow = ui.texture {
|
|
path = 'textures/omw_menu_scroll_left.dds',
|
|
}
|
|
local rightArrow = ui.texture {
|
|
path = 'textures/omw_menu_scroll_right.dds',
|
|
}
|
|
registerRenderer('select', function(value, set, argument)
|
|
argument = applyDefaults(argument, defaultArgument)
|
|
if not argument.l10n then
|
|
error('"select" renderer requires a "l10n" argument')
|
|
end
|
|
if not pcall(function()
|
|
local _ = ipairs(argument.items)
|
|
assert(#argument.items > 0)
|
|
end)
|
|
then
|
|
error('"select" renderer requires an "items" array as an argument')
|
|
end
|
|
local l10n = core.l10n(argument.l10n)
|
|
local index = nil
|
|
local itemCount = #argument.items
|
|
for i, item in ipairs(argument.items) do
|
|
if item == value then
|
|
index = i
|
|
end
|
|
end
|
|
local label = l10n(tostring(value))
|
|
local labelColor = nil
|
|
if index == nil then
|
|
labelColor = util.color.rgb(1, 0, 0)
|
|
end
|
|
local body = {
|
|
type = ui.TYPE.Flex,
|
|
props = {
|
|
horizontal = true,
|
|
arrange = ui.ALIGNMENT.Center,
|
|
},
|
|
content = ui.content {
|
|
{
|
|
type = ui.TYPE.Image,
|
|
props = {
|
|
resource = leftArrow,
|
|
size = util.vector2(1, 1) * 12,
|
|
},
|
|
events = {
|
|
mouseClick = async:callback(function()
|
|
if not index then
|
|
set(argument.items[#argument.items])
|
|
return
|
|
end
|
|
index = (index - 2) % itemCount + 1
|
|
set(argument.items[index])
|
|
end),
|
|
},
|
|
},
|
|
{ template = I.MWUI.templates.interval },
|
|
{
|
|
template = I.MWUI.templates.textNormal,
|
|
props = {
|
|
text = label,
|
|
textColor = labelColor,
|
|
},
|
|
external = {
|
|
grow = 1,
|
|
},
|
|
},
|
|
{ template = I.MWUI.templates.interval },
|
|
{
|
|
type = ui.TYPE.Image,
|
|
props = {
|
|
resource = rightArrow,
|
|
size = util.vector2(1, 1) * 12,
|
|
},
|
|
events = {
|
|
mouseClick = async:callback(function()
|
|
if not index then
|
|
set(argument.items[1])
|
|
return
|
|
end
|
|
index = (index) % itemCount + 1
|
|
set(argument.items[index])
|
|
end),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
return disable(argument.disabled, paddedBox(body))
|
|
end)
|
|
end
|
|
|
|
do
|
|
local whiteTexture = ui.texture { path = 'white' }
|
|
local defaultArgument = {
|
|
disabled = false,
|
|
}
|
|
registerRenderer('color', function(value, set, argument)
|
|
argument = applyDefaults(argument, defaultArgument)
|
|
local colorDisplay = {
|
|
template = I.MWUI.templates.box,
|
|
content = ui.content {
|
|
{
|
|
type = ui.TYPE.Image,
|
|
props = {
|
|
resource = whiteTexture,
|
|
color = value,
|
|
-- TODO: remove hardcoded size when possible
|
|
size = util.vector2(1, 1) * 20,
|
|
},
|
|
}
|
|
},
|
|
}
|
|
local lastInput = nil
|
|
local hexInput = paddedBox {
|
|
template = I.MWUI.templates.textEditLine,
|
|
props = {
|
|
text = value:asHex(),
|
|
},
|
|
events = {
|
|
textChanged = async:callback(function(text)
|
|
lastInput = text
|
|
end),
|
|
focusLoss = async:callback(function()
|
|
if not lastInput then return end
|
|
if not pcall(function() set(util.color.hex(lastInput)) end)
|
|
then
|
|
set(value)
|
|
end
|
|
end),
|
|
},
|
|
}
|
|
return disable(argument.disabled, {
|
|
type = ui.TYPE.Flex,
|
|
props = {
|
|
horizontal = true,
|
|
arrange = ui.ALIGNMENT.Center,
|
|
},
|
|
content = ui.content {
|
|
colorDisplay,
|
|
{ template = I.MWUI.templates.interval },
|
|
hexInput,
|
|
}
|
|
})
|
|
end)
|
|
end
|
|
end
|