mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 12:35:46 +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)
|
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)
|
mCallbacks.erase(std::remove_if(mCallbacks.begin(), mCallbacks.end(), [&](const Callback& callback)
|
||||||
{
|
{
|
||||||
bool valid = callback.isValid();
|
bool valid = callback.isValid();
|
||||||
@ -46,13 +46,20 @@ namespace LuaUtil
|
|||||||
callback.tryCall(mSectionName, changedKey);
|
callback.tryCall(mSectionName, changedKey);
|
||||||
return !valid;
|
return !valid;
|
||||||
}), mCallbacks.end());
|
}), 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)
|
void LuaStorage::Section::set(std::string_view key, const sol::object& value)
|
||||||
{
|
{
|
||||||
if (mStorage->mRunningCallbacks)
|
throwIfCallbackRecursionIsTooDeep();
|
||||||
throw std::runtime_error("Not allowed to change storage in storage handlers because it can lead to an infinite recursion");
|
|
||||||
if (value != sol::nil)
|
if (value != sol::nil)
|
||||||
mValues[std::string(key)] = Value(value);
|
mValues[std::string(key)] = Value(value);
|
||||||
else
|
else
|
||||||
@ -68,8 +75,7 @@ namespace LuaUtil
|
|||||||
|
|
||||||
void LuaStorage::Section::setAll(const sol::optional<sol::table>& values)
|
void LuaStorage::Section::setAll(const sol::optional<sol::table>& values)
|
||||||
{
|
{
|
||||||
if (mStorage->mRunningCallbacks)
|
throwIfCallbackRecursionIsTooDeep();
|
||||||
throw std::runtime_error("Not allowed to change storage in storage handlers because it can lead to an infinite recursion");
|
|
||||||
mValues.clear();
|
mValues.clear();
|
||||||
if (values)
|
if (values)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,7 @@ namespace LuaUtil
|
|||||||
void setAll(const sol::optional<sol::table>& values);
|
void setAll(const sol::optional<sol::table>& values);
|
||||||
sol::table asTable();
|
sol::table asTable();
|
||||||
void runCallbacks(sol::optional<std::string_view> changedKey);
|
void runCallbacks(sol::optional<std::string_view> changedKey);
|
||||||
|
void throwIfCallbackRecursionIsTooDeep();
|
||||||
|
|
||||||
LuaStorage* mStorage;
|
LuaStorage* mStorage;
|
||||||
std::string mSectionName;
|
std::string mSectionName;
|
||||||
@ -81,7 +82,7 @@ namespace LuaUtil
|
|||||||
lua_State* mLua;
|
lua_State* mLua;
|
||||||
std::map<std::string_view, std::shared_ptr<Section>> mData;
|
std::map<std::string_view, std::shared_ptr<Section>> mData;
|
||||||
const Listener* mListener = nullptr;
|
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/constants.lua
|
||||||
scripts/omw/mwui/borders.lua
|
scripts/omw/mwui/borders.lua
|
||||||
scripts/omw/mwui/box.lua
|
scripts/omw/mwui/filters.lua
|
||||||
scripts/omw/mwui/text.lua
|
scripts/omw/mwui/text.lua
|
||||||
scripts/omw/mwui/textEdit.lua
|
scripts/omw/mwui/textEdit.lua
|
||||||
scripts/omw/mwui/space.lua
|
scripts/omw/mwui/space.lua
|
||||||
|
@ -6,7 +6,7 @@ local auxUi = require('openmw_aux.ui')
|
|||||||
local constants = require('scripts.omw.mwui.constants')
|
local constants = require('scripts.omw.mwui.constants')
|
||||||
|
|
||||||
local v2 = util.vector2
|
local v2 = util.vector2
|
||||||
local whiteTexture = ui.texture{ path = 'white' }
|
local whiteTexture = constants.whiteTexture
|
||||||
local menuTransparency = ui._getMenuTransparency()
|
local menuTransparency = ui._getMenuTransparency()
|
||||||
|
|
||||||
local sideParts = {
|
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')
|
local util = require('openmw.util')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -8,4 +9,5 @@ return {
|
|||||||
border = 2,
|
border = 2,
|
||||||
thickBorder = 4,
|
thickBorder = 4,
|
||||||
padding = 2,
|
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
|
-- @field [parent=#Templates] openmw.ui#Layout textEditBox
|
||||||
require('scripts.omw.mwui.textEdit')(templates)
|
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
|
-- Interface version
|
||||||
-- @field [parent=#MWUI] #number version
|
-- @field [parent=#MWUI] #number version
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
local storage = require('openmw.storage')
|
local storage = require('openmw.storage')
|
||||||
|
|
||||||
local contextSection = storage.playerSection or storage.globalSection
|
|
||||||
local groupSectionKey = 'OmwSettingGroups'
|
local groupSectionKey = 'OmwSettingGroups'
|
||||||
|
local conventionPrefix = 'Settings'
|
||||||
|
local argumentSectionPostfix = 'Arguments'
|
||||||
|
|
||||||
|
local contextSection = storage.playerSection or storage.globalSection
|
||||||
local groupSection = contextSection(groupSectionKey)
|
local groupSection = contextSection(groupSectionKey)
|
||||||
groupSection:removeOnExit()
|
groupSection:removeOnExit()
|
||||||
|
|
||||||
@ -30,7 +33,6 @@ local function validateGroupOptions(options)
|
|||||||
if type(options.key) ~= 'string' then
|
if type(options.key) ~= 'string' then
|
||||||
error('Group must have a key')
|
error('Group must have a key')
|
||||||
end
|
end
|
||||||
local conventionPrefix = "Settings"
|
|
||||||
if options.key:sub(1, conventionPrefix:len()) ~= conventionPrefix then
|
if options.key:sub(1, conventionPrefix:len()) ~= conventionPrefix then
|
||||||
print(("Group key %s doesn't start with %s"):format(options.key, conventionPrefix))
|
print(("Group key %s doesn't start with %s"):format(options.key, conventionPrefix))
|
||||||
end
|
end
|
||||||
@ -88,6 +90,8 @@ local function registerGroup(options)
|
|||||||
settings = {},
|
settings = {},
|
||||||
}
|
}
|
||||||
local valueSection = contextSection(options.key)
|
local valueSection = contextSection(options.key)
|
||||||
|
local argumentSection = contextSection(options.key .. argumentSectionPostfix)
|
||||||
|
argumentSection:removeOnExit()
|
||||||
for i, opt in ipairs(options.settings) do
|
for i, opt in ipairs(options.settings) do
|
||||||
local setting = registerSetting(opt)
|
local setting = registerSetting(opt)
|
||||||
setting.order = i
|
setting.order = i
|
||||||
@ -95,9 +99,10 @@ local function registerGroup(options)
|
|||||||
error(('Duplicate setting key %s'):format(options.key))
|
error(('Duplicate setting key %s'):format(options.key))
|
||||||
end
|
end
|
||||||
group.settings[setting.key] = setting
|
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)
|
valueSection:set(setting.key, setting.default)
|
||||||
end
|
end
|
||||||
|
argumentSection:set(setting.key, setting.argument)
|
||||||
end
|
end
|
||||||
groupSection:set(group.key, group)
|
groupSection:set(group.key, group)
|
||||||
end
|
end
|
||||||
@ -106,6 +111,13 @@ return {
|
|||||||
getSection = function(global, key)
|
getSection = function(global, key)
|
||||||
return (global and storage.globalSection or storage.playerSection)(key)
|
return (global and storage.globalSection or storage.playerSection)(key)
|
||||||
end,
|
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',
|
setGlobalEvent = 'OMWSettingsGlobalSet',
|
||||||
groupSectionKey = groupSectionKey,
|
groupSectionKey = groupSectionKey,
|
||||||
onLoad = function(saved)
|
onLoad = function(saved)
|
||||||
|
@ -6,6 +6,7 @@ return {
|
|||||||
interfaceName = 'Settings',
|
interfaceName = 'Settings',
|
||||||
interface = {
|
interface = {
|
||||||
registerGroup = common.registerGroup,
|
registerGroup = common.registerGroup,
|
||||||
|
updateRendererArgument = common.updateRendererArgument,
|
||||||
},
|
},
|
||||||
engineHandlers = {
|
engineHandlers = {
|
||||||
onLoad = common.onLoad,
|
onLoad = common.onLoad,
|
||||||
|
@ -137,6 +137,13 @@ return {
|
|||||||
-- }
|
-- }
|
||||||
-- }
|
-- }
|
||||||
registerGroup = common.registerGroup,
|
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 = {
|
engineHandlers = {
|
||||||
onLoad = common.onLoad,
|
onLoad = common.onLoad,
|
||||||
|
@ -110,6 +110,7 @@ local function renderSetting(group, setting, value, global)
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
local argument = common.getArgumentSection(global, group.key):get(setting.key)
|
||||||
return {
|
return {
|
||||||
name = setting.key,
|
name = setting.key,
|
||||||
type = ui.TYPE.Flex,
|
type = ui.TYPE.Flex,
|
||||||
@ -123,7 +124,7 @@ local function renderSetting(group, setting, value, global)
|
|||||||
content = ui.content {
|
content = ui.content {
|
||||||
titleLayout,
|
titleLayout,
|
||||||
growingIntreval,
|
growingIntreval,
|
||||||
renderFunction(value, set, setting.argument),
|
renderFunction(value, set, argument),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@ -350,6 +351,20 @@ local function onGroupRegistered(global, key)
|
|||||||
}
|
}
|
||||||
table.insert(groups[group.page], pageGroup)
|
table.insert(groups[group.page], pageGroup)
|
||||||
common.getSection(global, group.key):subscribe(onSettingChanged(global))
|
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
|
if not pages[group.page] then return end
|
||||||
local options = renderPage(pages[group.page])
|
local options = renderPage(pages[group.page])
|
||||||
|
@ -2,38 +2,80 @@ local ui = require('openmw.ui')
|
|||||||
local async = require('openmw.async')
|
local async = require('openmw.async')
|
||||||
local I = require('openmw.interfaces')
|
local I = require('openmw.interfaces')
|
||||||
|
|
||||||
return function(registerRenderer)
|
local function applyDefaults(argument, defaults)
|
||||||
registerRenderer('textLine', function(value, set)
|
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 {
|
return {
|
||||||
template = I.MWUI.templates.textEditLine,
|
template = I.MWUI.templates.disabled,
|
||||||
props = {
|
content = ui.content {
|
||||||
text = tostring(value),
|
layout,
|
||||||
},
|
|
||||||
events = {
|
|
||||||
textChanged = async:callback(function(s) set(s) end),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end)
|
else
|
||||||
|
return layout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
registerRenderer('yesNo', function(value, set)
|
return function(registerRenderer)
|
||||||
return {
|
do
|
||||||
template = I.MWUI.templates.box,
|
local defaultArgument = {
|
||||||
content = ui.content {
|
disabled = false,
|
||||||
{
|
}
|
||||||
template = I.MWUI.templates.padding,
|
registerRenderer('textLine', function(value, set, argument)
|
||||||
content = ui.content {
|
argument = applyDefaults(argument, defaultArgument)
|
||||||
{
|
return disable(argument.disabled, {
|
||||||
template = I.MWUI.templates.textNormal,
|
template = I.MWUI.templates.textEditLine,
|
||||||
props = {
|
props = {
|
||||||
text = value and 'Yes' or 'No',
|
text = tostring(value),
|
||||||
},
|
},
|
||||||
events = {
|
events = {
|
||||||
mouseClick = async:callback(function() set(not value) end),
|
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
|
end
|
Loading…
x
Reference in New Issue
Block a user