Changing setting renderer arguments

openmw-fix_osx_build_maybe
uramer 2 years ago committed by Petr Mikheev
parent b832ba5c83
commit 1fe794d935

@ -38,7 +38,7 @@ namespace LuaUtil
void LuaStorage::Section::runCallbacks(sol::optional<std::string_view> changedKey)
{
mStorage->mRunningCallbacks = true;
mStorage->mRunningCallbacks.insert(this);
mCallbacks.erase(std::remove_if(mCallbacks.begin(), mCallbacks.end(), [&](const Callback& callback)
{
bool valid = callback.isValid();
@ -46,13 +46,20 @@ namespace LuaUtil
callback.tryCall(mSectionName, changedKey);
return !valid;
}), mCallbacks.end());
mStorage->mRunningCallbacks = false;
mStorage->mRunningCallbacks.erase(this);
}
void LuaStorage::Section::throwIfCallbackRecursionIsTooDeep()
{
if (mStorage->mRunningCallbacks.count(this) > 0)
throw std::runtime_error("Storage handler shouldn't change the storage section it handles (leads to an infinite recursion)");
if (mStorage->mRunningCallbacks.size() > 10)
throw std::runtime_error("Too many subscribe callbacks triggering in a chain, likely an infinite recursion");
}
void LuaStorage::Section::set(std::string_view key, const sol::object& value)
{
if (mStorage->mRunningCallbacks)
throw std::runtime_error("Not allowed to change storage in storage handlers because it can lead to an infinite recursion");
throwIfCallbackRecursionIsTooDeep();
if (value != sol::nil)
mValues[std::string(key)] = Value(value);
else
@ -68,8 +75,7 @@ namespace LuaUtil
void LuaStorage::Section::setAll(const sol::optional<sol::table>& values)
{
if (mStorage->mRunningCallbacks)
throw std::runtime_error("Not allowed to change storage in storage handlers because it can lead to an infinite recursion");
throwIfCallbackRecursionIsTooDeep();
mValues.clear();
if (values)
{

@ -62,6 +62,7 @@ namespace LuaUtil
void setAll(const sol::optional<sol::table>& values);
sol::table asTable();
void runCallbacks(sol::optional<std::string_view> changedKey);
void throwIfCallbackRecursionIsTooDeep();
LuaStorage* mStorage;
std::string mSectionName;
@ -81,7 +82,7 @@ namespace LuaUtil
lua_State* mLua;
std::map<std::string_view, std::shared_ptr<Section>> mData;
const Listener* mListener = nullptr;
bool mRunningCallbacks = false;
std::set<const Section*> mRunningCallbacks;
};
}

@ -27,7 +27,7 @@ set(LUA_BUILTIN_FILES
scripts/omw/mwui/constants.lua
scripts/omw/mwui/borders.lua
scripts/omw/mwui/box.lua
scripts/omw/mwui/filters.lua
scripts/omw/mwui/text.lua
scripts/omw/mwui/textEdit.lua
scripts/omw/mwui/space.lua

@ -6,7 +6,7 @@ local auxUi = require('openmw_aux.ui')
local constants = require('scripts.omw.mwui.constants')
local v2 = util.vector2
local whiteTexture = ui.texture{ path = 'white' }
local whiteTexture = constants.whiteTexture
local menuTransparency = ui._getMenuTransparency()
local sideParts = {

@ -1,45 +0,0 @@
local ui = require('openmw.ui')
local util = require('openmw.util')
local whiteTexture = ui.texture{ path = 'white' }
local menuTransparency = ui._getMenuTransparency()
return function(templates)
templates.backgroundTransparent = {
props = {
resource = whiteTexture,
color = util.color.rgb(0, 0, 0),
alpha = menuTransparency,
},
}
templates.backgroundSolid = {
props = {
resource = whiteTexture,
color = util.color.rgb(0, 0, 0),
},
}
templates.box = {
props = {
inheritAlpha = false,
},
content = ui.content {
{
type = ui.TYPE.Image,
template = templates.backgroundTransparent,
props = {
relativeSize = util.vector2(1, 1),
},
},
{
template = templates.borders,
props = {
relativeSize = util.vector2(1, 1),
},
external = {
slot = true,
},
},
},
}
end

@ -1,3 +1,4 @@
local ui = require('openmw.ui')
local util = require('openmw.util')
return {
@ -8,4 +9,5 @@ return {
border = 2,
thickBorder = 4,
padding = 2,
whiteTexture = ui.texture { path = 'white' },
}

@ -0,0 +1,31 @@
local ui = require('openmw.ui')
local util = require('openmw.util')
local constants = require('scripts.omw.mwui.constants')
return function(templates)
templates.disabled = {
type = ui.TYPE.Container,
props = {
alpha = 0.6,
},
content = ui.content {
{
props = {
relativeSize = util.vector2(1, 1),
},
external = {
slot = true,
},
},
{
type = ui.TYPE.Image,
props = {
resource = constants.whiteTexture,
color = util.color.rgb(0, 0, 0),
relativeSize = util.vector2(1, 1),
},
},
},
}
end

@ -93,6 +93,11 @@ require('scripts.omw.mwui.text')(templates)
-- @field [parent=#Templates] openmw.ui#Layout textEditBox
require('scripts.omw.mwui.textEdit')(templates)
---
-- Shades its children and makes them uninteractible
-- @field [parent=#Templates] openmw.ui#Layout disabled
require('scripts.omw.mwui.filters')(templates)
---
-- Interface version
-- @field [parent=#MWUI] #number version

@ -1,7 +1,10 @@
local storage = require('openmw.storage')
local contextSection = storage.playerSection or storage.globalSection
local groupSectionKey = 'OmwSettingGroups'
local conventionPrefix = 'Settings'
local argumentSectionPostfix = 'Arguments'
local contextSection = storage.playerSection or storage.globalSection
local groupSection = contextSection(groupSectionKey)
groupSection:removeOnExit()
@ -30,7 +33,6 @@ local function validateGroupOptions(options)
if type(options.key) ~= 'string' then
error('Group must have a key')
end
local conventionPrefix = "Settings"
if options.key:sub(1, conventionPrefix:len()) ~= conventionPrefix then
print(("Group key %s doesn't start with %s"):format(options.key, conventionPrefix))
end
@ -88,6 +90,8 @@ local function registerGroup(options)
settings = {},
}
local valueSection = contextSection(options.key)
local argumentSection = contextSection(options.key .. argumentSectionPostfix)
argumentSection:removeOnExit()
for i, opt in ipairs(options.settings) do
local setting = registerSetting(opt)
setting.order = i
@ -95,9 +99,10 @@ local function registerGroup(options)
error(('Duplicate setting key %s'):format(options.key))
end
group.settings[setting.key] = setting
if not valueSection:get(setting.key) then
if valueSection:get(setting.key) == nil then
valueSection:set(setting.key, setting.default)
end
argumentSection:set(setting.key, setting.argument)
end
groupSection:set(group.key, group)
end
@ -106,6 +111,13 @@ return {
getSection = function(global, key)
return (global and storage.globalSection or storage.playerSection)(key)
end,
getArgumentSection = function(global, key)
return (global and storage.globalSection or storage.playerSection)(key .. argumentSectionPostfix)
end,
updateRendererArgument = function(groupKey, settingKey, argument)
local argumentSection = contextSection(groupKey .. argumentSectionPostfix)
argumentSection:set(settingKey, argument)
end,
setGlobalEvent = 'OMWSettingsGlobalSet',
groupSectionKey = groupSectionKey,
onLoad = function(saved)

@ -6,6 +6,7 @@ return {
interfaceName = 'Settings',
interface = {
registerGroup = common.registerGroup,
updateRendererArgument = common.updateRendererArgument,
},
engineHandlers = {
onLoad = common.onLoad,

@ -137,6 +137,13 @@ return {
-- }
-- }
registerGroup = common.registerGroup,
---
-- @function [parent=#Settings] updateRendererArgument Change the renderer argument of a setting
-- available both in player and global scripts
-- @param #string groupKey A settings group key
-- @param #string settingKey A setting key
-- @param argument A renderer argument
updateRendererArgument = common.updateRendererArgument,
},
engineHandlers = {
onLoad = common.onLoad,

@ -110,6 +110,7 @@ local function renderSetting(group, setting, value, global)
},
}
end
local argument = common.getArgumentSection(global, group.key):get(setting.key)
return {
name = setting.key,
type = ui.TYPE.Flex,
@ -123,7 +124,7 @@ local function renderSetting(group, setting, value, global)
content = ui.content {
titleLayout,
growingIntreval,
renderFunction(value, set, setting.argument),
renderFunction(value, set, argument),
},
}
end
@ -350,6 +351,20 @@ local function onGroupRegistered(global, key)
}
table.insert(groups[group.page], pageGroup)
common.getSection(global, group.key):subscribe(onSettingChanged(global))
common.getArgumentSection(global, group.key):subscribe(async:callback(function(_, settingKey)
local groupKey = group.key
local group = common.getSection(global, common.groupSectionKey):get(groupKey)
if not group or not pageOptions[group.page] then 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()
end))
if not pages[group.page] then return end
local options = renderPage(pages[group.page])

@ -2,38 +2,80 @@ local ui = require('openmw.ui')
local async = require('openmw.async')
local I = require('openmw.interfaces')
return function(registerRenderer)
registerRenderer('textLine', function(value, set)
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 disable(disabled, layout)
if disabled then
return {
template = I.MWUI.templates.textEditLine,
props = {
text = tostring(value),
},
events = {
textChanged = async:callback(function(s) set(s) end),
template = I.MWUI.templates.disabled,
content = ui.content {
layout,
},
}
end)
else
return layout
end
end
registerRenderer('yesNo', function(value, set)
return {
template = I.MWUI.templates.box,
content = ui.content {
{
template = I.MWUI.templates.padding,
content = ui.content {
{
template = I.MWUI.templates.textNormal,
props = {
text = value and 'Yes' or 'No',
},
events = {
mouseClick = async:callback(function() set(not value) end),
return function(registerRenderer)
do
local defaultArgument = {
disabled = false,
}
registerRenderer('textLine', function(value, set, argument)
argument = applyDefaults(argument, defaultArgument)
return disable(argument.disabled, {
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,
trueLabel = 'Yes',
falseLabel = 'No',
}
registerRenderer('checkbox', function(value, set, argument)
argument = applyDefaults(argument, defaultArgument)
return disable(argument.disabled, {
template = I.MWUI.templates.box,
content = ui.content {
{
template = I.MWUI.templates.padding,
content = ui.content {
{
template = I.MWUI.templates.textNormal,
props = {
text = value and argument.trueLabel or argument.falseLabel
},
events = {
mouseClick = async:callback(function() set(not value) end),
},
},
},
},
},
},
}
end)
})
end)
end
end
Loading…
Cancel
Save