From a11e553de4000052e5f03ef9acbe360f460d9581 Mon Sep 17 00:00:00 2001 From: uramer Date: Wed, 6 Mar 2024 22:23:07 +0100 Subject: [PATCH] Optimize setting group rendering by rendering them as separate elements, support element-rendered setting renderers --- files/data/scripts/omw/settings/menu.lua | 70 +++++++++++++++++------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/files/data/scripts/omw/settings/menu.lua b/files/data/scripts/omw/settings/menu.lua index 2246b5ad7e..7d425f684b 100644 --- a/files/data/scripts/omw/settings/menu.lua +++ b/files/data/scripts/omw/settings/menu.lua @@ -6,8 +6,11 @@ local core = require('openmw.core') local storage = require('openmw.storage') local I = require('openmw.interfaces') +local auxUi = require('openmw_aux.ui') + local common = require('scripts.omw.settings.common') --- :reset on startup instead of :removeOnExit +common.getSection(false, common.groupSectionKey):setLifeTime(storage.LIFE_TIME.GameSession) +-- need to :reset() on reloadlua as well as game session end common.getSection(false, common.groupSectionKey):reset() local renderers = {} @@ -21,6 +24,7 @@ local interfaceL10n = core.l10n('Interface') local pages = {} local groups = {} local pageOptions = {} +local groupElements = {} local interval = { template = I.MWUI.templates.interval } local growingIntreval = { @@ -116,6 +120,11 @@ local function renderSetting(group, setting, value, global) } end local argument = common.getArgumentSection(global, group.key):get(setting.key) + local ok, rendererResult = pcall(renderFunction, value, set, argument) + if not ok then + print(string.format('Setting %s renderer "%s" error: %s', setting.key, setting.renderer, rendererResult)) + end + return { name = setting.key, type = ui.TYPE.Flex, @@ -129,7 +138,7 @@ local function renderSetting(group, setting, value, global) content = ui.content { titleLayout, growingIntreval, - renderFunction(value, set, argument), + ok and rendererResult or {}, -- TODO: display error? }, } end @@ -245,10 +254,12 @@ end local function generateSearchHints(page) local hints = {} - local l10n = core.l10n(page.l10n) - table.insert(hints, l10n(page.name)) - if page.description then - table.insert(hints, l10n(page.description)) + do + local l10n = core.l10n(page.l10n) + table.insert(hints, l10n(page.name)) + if page.description then + table.insert(hints, l10n(page.description)) + end end local pageGroups = groups[page.key] for _, pageGroup in pairs(pageGroups) do @@ -281,7 +292,15 @@ local function renderPage(page, options) if not group then error(string.format('%s group "%s" was not found', pageGroup.global and 'Global' or 'Player', pageGroup.key)) end - table.insert(groupLayouts, renderGroup(group, pageGroup.global)) + local groupElement = groupElements[page.key][group.key] + if not groupElement or not groupElement.layout then + groupElement = ui.create(renderGroup(group, pageGroup.global)) + end + if groupElement.layout == nil then + error(string.format('Destroyed group element for %s %s', page.key, group.key)) + end + groupElements[page.key][group.key] = groupElement + table.insert(groupLayouts, groupElement) end local groupsLayout = { name = 'groups', @@ -344,18 +363,23 @@ local function onSettingChanged(global) local group = common.getSection(global, common.groupSectionKey):get(groupKey) if not group or not pageOptions[group.page] then return end + local groupElement = groupElements[group.page][group.key] + if not settingKey then - renderPage(pages[group.page], pageOptions[group.page]) + if groupElement then + groupElement.layout = renderGroup(group) + groupElement:update() + else + renderPage(pages[group.page], pageOptions[group.page]) + end return end local value = common.getSection(global, group.key):get(settingKey) - local element = pageOptions[group.page].element - local groupsLayout = element.layout.content.groups - local groupLayout = groupsLayout.content[groupLayoutName(group.key, global)] - local settingsContent = groupLayout.content.settings.content - settingsContent[settingKey] = renderSetting(group, group.settings[settingKey], value, global) - element:update() + local settingsContent = groupElement.layout.content.settings.content + auxUi.deepDestroy(settingsContent[settingKey]) -- support setting renderers which return UI elements + settingsContent[settingKey] = renderSetting(group, group.settings[settingKey], value) + groupElement:update() end) end @@ -364,6 +388,8 @@ local function onGroupRegistered(global, key) if not group then return end groups[group.page] = groups[group.page] or {} + groupElements[group.page] = groupElements[group.page] or {} + local pageGroup = { key = group.key, global = global, @@ -380,11 +406,9 @@ local function onGroupRegistered(global, key) local value = common.getSection(global, group.key):get(settingKey) - local element = pageOptions[group.page].element - local groupsLayout = element.layout.content.groups - local groupLayout = groupsLayout.content[groupLayoutName(group.key, global)] - local settingsContent = groupLayout.content.settings.content - settingsContent[settingKey] = renderSetting(group, group.settings[settingKey], value, global) + local element = groupElements[group.page][group.key] + local settingsContent = element.layout.content.settings.content + settingsContent[settingKey] = renderSetting(group, group.settings[settingKey], value) element:update() end)) end @@ -422,6 +446,11 @@ local function resetPlayerGroups() for pageKey, page in pairs(groups) do for groupKey in pairs(page) do if not menuGroups[groupKey] then + if groupElements[pageKey][groupKey] then + groupElements[pageKey][groupKey]:destroy() + print(string.format('destroyed group element %s %s', pageKey, groupKey)) + groupElements[pageKey][groupKey] = nil + end page[groupKey] = nil playerGroupsSection:set(groupKey, nil) end @@ -430,7 +459,8 @@ local function resetPlayerGroups() if options then if not menuPages[pageKey] then if options.element then - options.element:destroy() + auxUi.deepDestroy(options.element) + options.element = nil end ui.removeSettingsPage(options) pageOptions[pageKey] = nil