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.
openmw/files/data/scripts/omw/settings/renderers.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