mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 03:56:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			267 lines
		
	
	
	
		
			8.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			267 lines
		
	
	
	
		
			8.9 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
 | 
						|
            local l10n = core.l10n(argument.l10n)
 | 
						|
            local index = nil
 | 
						|
            local itemCount = 0
 | 
						|
            for i, item in ipairs(argument.items) do
 | 
						|
                itemCount = itemCount + 1
 | 
						|
                if item == value then
 | 
						|
                    index = i
 | 
						|
                end
 | 
						|
            end
 | 
						|
            if not index then return {} end
 | 
						|
            local label = l10n(value)
 | 
						|
            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()
 | 
						|
                                index = (index - 2) % itemCount + 1
 | 
						|
                                set(argument.items[index])
 | 
						|
                            end),
 | 
						|
                        },
 | 
						|
                    },
 | 
						|
                    { template = I.MWUI.templates.interval },
 | 
						|
                    {
 | 
						|
                        template = I.MWUI.templates.textNormal,
 | 
						|
                        props = {
 | 
						|
                            text = label,
 | 
						|
                        },
 | 
						|
                        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()
 | 
						|
                                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
 |