mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 18:35:20 +00:00
Merge branch 'change_renderer_args' into 'master'
Changing setting renderer arguments See merge request OpenMW/openmw!1875
This commit is contained in:
commit
84ef84529a
@ -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' },
|
||||
}
|
31
files/builtin_scripts/scripts/omw/mwui/filters.lua
Normal file
31
files/builtin_scripts/scripts/omw/mwui/filters.lua
Normal file
@ -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…
x
Reference in New Issue
Block a user