Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-12-29 15:29:20 +1100
committerGitHub <noreply@github.com>2024-12-29 15:29:20 +1100
commitb953042e56f67c3e60391ed8911f7561c5ea609e (patch)
tree1d820dd92b439eb03611987c9730fc4f52f50152
parent75ff3cbba9b44a357af0e24ec99a0c28fcdf8d43 (diff)
parentec6c8f0c3c72cd7a9c9ea97721f12225cff42406 (diff)
Merge pull request #158 from Bottinator22/main
Scriptable shader uniforms
-rw-r--r--assets/opensb/interface/opensb/shaders/select.pngbin0 -> 4583 bytes
-rw-r--r--assets/opensb/interface/opensb/shaders/selectend.pngbin0 -> 4094 bytes
-rw-r--r--assets/opensb/interface/opensb/shaders/shaders.config5
-rw-r--r--assets/opensb/interface/opensb/shaders/shaders.lua152
-rw-r--r--assets/opensb/scripts/opensb/universeclient/loadconfig.lua22
-rw-r--r--assets/opensb/scripts/opensb/universeclient/universeclient.lua2
-rw-r--r--source/application/StarRenderer.hpp5
-rw-r--r--source/application/StarRenderer_opengl.cpp112
-rw-r--r--source/application/StarRenderer_opengl.hpp4
-rw-r--r--source/client/StarRenderingLuaBindings.cpp24
-rw-r--r--source/core/StarLuaConverters.hpp8
-rw-r--r--source/windowing/StarScrollArea.cpp3
12 files changed, 309 insertions, 28 deletions
diff --git a/assets/opensb/interface/opensb/shaders/select.png b/assets/opensb/interface/opensb/shaders/select.png
new file mode 100644
index 0000000..dc649b4
--- /dev/null
+++ b/assets/opensb/interface/opensb/shaders/select.png
Binary files differ
diff --git a/assets/opensb/interface/opensb/shaders/selectend.png b/assets/opensb/interface/opensb/shaders/selectend.png
new file mode 100644
index 0000000..99908d6
--- /dev/null
+++ b/assets/opensb/interface/opensb/shaders/selectend.png
Binary files differ
diff --git a/assets/opensb/interface/opensb/shaders/shaders.config b/assets/opensb/interface/opensb/shaders/shaders.config
index 5154831..864574e 100644
--- a/assets/opensb/interface/opensb/shaders/shaders.config
+++ b/assets/opensb/interface/opensb/shaders/shaders.config
@@ -3,7 +3,10 @@
"scriptDelta" : 0,
"scriptWidgetCallbacks" : [
"selectGroup",
- "toggleGroupEnabled"
+ "toggleGroupEnabled",
+ "sliderOptionModified",
+ "textboxOptionModified",
+ "selectOptionPressed"
],
"gui" : {
diff --git a/assets/opensb/interface/opensb/shaders/shaders.lua b/assets/opensb/interface/opensb/shaders/shaders.lua
index 0030b5c..0c2d19c 100644
--- a/assets/opensb/interface/opensb/shaders/shaders.lua
+++ b/assets/opensb/interface/opensb/shaders/shaders.lua
@@ -17,6 +17,14 @@ local groups = {}
local widgetsToGroups = {}
local allSettings = {}
+local shaderConfig
+
+function displayed()
+ shaderConfig = root.getConfiguration("postProcessGroups")
+end
+function dismissed()
+ shaderConfig = nil
+end
local function addGroupToList(data)
local name = widget.addListItem(GROUP_LIST_WIDGET)
@@ -67,7 +75,7 @@ local function addOptionGroup(data, i, added)
added[#added + 1] = name
local label = {
type = "label",
- value = data.name,
+ value = data.label,
wrapWidth = 120,
fontSize = 8,
hAnchor = "mid",
@@ -77,6 +85,16 @@ local function addOptionGroup(data, i, added)
widget.addChild(fmt("%s.%s", BINDS_WIDGET, name), label, "text")
end
+local function digitRegex(n)
+ local i = 0
+ while n ~= math.floor(n) do
+ n = n * 10
+ i = i + 1
+ end
+ return fmt("%%.%df",i) -- create format string %.nf, where n = %d (i with no decimal points)
+end
+local optionPrefix = "option_"
+local optionOffset = #optionPrefix+1
local function addOption(data, i, added)
local y = (i - 1) * -14
local bg = {
@@ -84,12 +102,12 @@ local function addOption(data, i, added)
file = PATH .. "optionname.png",
position = {-12, y}
}
- local name = "label_" .. i
+ local name = "label_" .. data.name
widget.addChild(OPTIONS_WIDGET, bg, name)
added[#added + 1] = name
local label = {
type = "label",
- value = data.name,
+ value = data.label,
wrapWidth = 120,
fontSize = 8,
hAnchor = "mid",
@@ -97,7 +115,115 @@ local function addOption(data, i, added)
position = {62, 6}
}
widget.addChild(fmt("%s.%s", OPTIONS_WIDGET, name), label, "text")
+ local value = data.default or 0
+ if not shaderConfig[activeGroup] then
+ shaderConfig[activeGroup] = {parameters={}}
+ end
+ if not shaderConfig[activeGroup].parameters then
+ shaderConfig[activeGroup].parameters = {}
+ end
+ if shaderConfig[activeGroup].parameters[data.name] ~= nil then
+ value = shaderConfig[activeGroup].parameters[data.name]
+ end
+
-- todo: finish this
+ if data.type == "slider" then
+ local range = data.range or {0,1}
+ local delta = data.delta or 0.01
+ -- for some reason ranges require ints so
+ local r = {range[1]/delta, range[2]/delta, 1}
+
+ local slider = {
+ type = "slider",
+ callback = "sliderOptionModified",
+ position = {110, y + 2},
+ gridImage = "/interface/optionsmenu/smallselection.png",
+ range = r
+ }
+ name = optionPrefix..data.name
+ added[#added + 1] = name
+ widget.addChild(OPTIONS_WIDGET, slider, name)
+
+ widget.setSliderValue(fmt("%s.%s",OPTIONS_WIDGET,name), value/delta)
+ local valLabel = {
+ type = "label",
+ value = fmt(digitRegex(delta),value),
+ position = {186, y + 2}
+ }
+ added[#added + 1] = name.."_value"
+ widget.addChild(OPTIONS_WIDGET, valLabel, name.."_value")
+ elseif data.type == "select" then
+ local n = #data.values
+ local width = math.floor(118/n)
+ local by = y
+ local buttons = {}
+ for i=0,n-1 do
+ local img = fmt("%sselect.png?crop=0;0;%.0f;13",PATH,width)
+ local button = {
+ type = "button",
+ callback="selectOptionPressed",
+ caption = data.values[i+1],
+ base = img,
+ hover = img.."?brightness=-25",
+ baseImageChecked = img.."?multiply=00ff00",
+ hoverImageChecked = img.."?multiply=00ff00?brightness=-25",
+ position = {110+width*i, by},
+ pressedOffset = {0, 0},
+ checkable = true,
+ checked = (value == i)
+ }
+ name = "select_"..data.name.."_"..i
+ added[#added + 1] = name
+ widget.addChild(OPTIONS_WIDGET, button, name)
+ table.insert(buttons,{widget=fmt("%s.%s",OPTIONS_WIDGET,name),index=i})
+ end
+ for k,v in next, buttons do
+ widget.setData(v.widget,{option=data,index=v.index,buttons=buttons})
+ end
+ --[[local bge = {
+ type = "image",
+ file = PATH.."selectend.png",
+ position = {110+width*3, by}
+ }
+ name = "bgend_"..data.name
+ added[#added + 1] = name
+ widget.addChild(OPTIONS_WIDGET, bge, name)]]
+ end
+end
+
+function sliderOptionModified(option, odata)
+ local oname = string.sub(option, optionOffset)
+ local parameter = groups[activeGroup].parameters[oname]
+ local value = widget.getSliderValue(fmt("%s.%s",OPTIONS_WIDGET,option))*parameter.delta
+
+ widget.setText(fmt("%s.%s",OPTIONS_WIDGET,option.."_value"), fmt(digitRegex(parameter.delta),value))
+
+ for k,v in next, parameter.effects do
+ renderer.setEffectParameter(v, oname, value)
+ end
+ shaderConfig[activeGroup].parameters[oname] = value
+ root.setConfiguration("postProcessGroups",shaderConfig)
+end
+
+function selectOptionPressed(button,bdata)
+ sb.logInfo(sb.print(bdata))
+
+ for k,v in next, bdata.buttons do
+ if v.index ~= bdata.index then
+ widget.setChecked(v.widget, false)
+ end
+ end
+
+ value = bdata.index
+
+ local oname = bdata.option.name
+ local parameter = groups[activeGroup].parameters[oname]
+
+ for k,v in next, parameter.effects do
+ renderer.setEffectParameter(v, oname, value)
+ end
+ shaderConfig[activeGroup].parameters[oname] = value
+ root.setConfiguration("postProcessGroups",shaderConfig)
end
local function addEnabled(groupname, i, added)
@@ -139,6 +265,7 @@ end
function toggleGroupEnabled(checkbox, cdata)
renderer.setPostProcessGroupEnabled(activeGroup, widget.getChecked(fmt("%s.%s",OPTIONS_WIDGET,checkbox)), true)
+ shaderConfig = root.getConfiguration("postProcessGroups")
end
function selectGroup()
@@ -163,7 +290,21 @@ function selectGroup()
local added = {}
local index = 0
addEnabled(group.groupId,index,added)
-
+ if group.categories then
+
+ elseif group.parameters then
+ local sortedParams = {}
+ for k,v in next, group.parameters do
+ v.name = k
+ sortedParams[#sortedParams+1] = v
+ end
+ table.sort(sortedParams, alphabeticalNameSortLesser)
+
+ for k,v in next, sortedParams do
+ index = index + 1
+ addOption(v, index, added)
+ end
+ end
--[[
local categories = group.categories or {}
if not categories.unsorted then
@@ -198,7 +339,8 @@ function selectGroup()
addOption(category.sortedOptions[iB], index, added)
end
end
- end]]
+ end
+ ]]
widget.setData(OPTIONS_WIDGET, added)
end
diff --git a/assets/opensb/scripts/opensb/universeclient/loadconfig.lua b/assets/opensb/scripts/opensb/universeclient/loadconfig.lua
new file mode 100644
index 0000000..2bb3ef8
--- /dev/null
+++ b/assets/opensb/scripts/opensb/universeclient/loadconfig.lua
@@ -0,0 +1,22 @@
+-- Meant to manage loading various miscellaneous things from configuration, such as shader parameters.
+
+local module = {}
+modules.config_loader = module
+
+function module.init()
+ local shaderConfig = root.getConfiguration("postProcessGroups") or {}
+ local postProcessGroups = renderer.postProcessGroups()
+ local changes = false
+ for k,v in next, shaderConfig do
+ local group = postProcessGroups[k]
+ if v.parameters then
+ for k2,v2 in next, group.parameters do
+ if v.parameters[k2] ~= nil then
+ for _,e in next, v2.effects do
+ renderer.setEffectParameter(e,k2,v.parameters[k2])
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/assets/opensb/scripts/opensb/universeclient/universeclient.lua b/assets/opensb/scripts/opensb/universeclient/universeclient.lua
index cad342b..a534c25 100644
--- a/assets/opensb/scripts/opensb/universeclient/universeclient.lua
+++ b/assets/opensb/scripts/opensb/universeclient/universeclient.lua
@@ -1,2 +1,2 @@
require "/scripts/opensb/util/modules.lua"
-modules("/scripts/opensb/universeclient/", {"voicemanager"}) \ No newline at end of file
+modules("/scripts/opensb/universeclient/", {"voicemanager","loadconfig"})
diff --git a/source/application/StarRenderer.hpp b/source/application/StarRenderer.hpp
index 2a156f7..2b106ff 100644
--- a/source/application/StarRenderer.hpp
+++ b/source/application/StarRenderer.hpp
@@ -120,7 +120,7 @@ public:
virtual void set(List<RenderPrimitive>& primitives) = 0;
};
-typedef Variant<bool, int, float, Vec2F, Vec3F, Vec4F> RenderEffectParameter;
+typedef Variant<float, int, Vec2F, Vec3F, Vec4F, bool> RenderEffectParameter;
class Renderer {
public:
@@ -141,6 +141,9 @@ public:
// The effect config will specify named parameters and textures which can be
// set here.
virtual void setEffectParameter(String const& parameterName, RenderEffectParameter const& parameter) = 0;
+ virtual void setEffectScriptableParameter(String const& effectName, String const& parameterName, RenderEffectParameter const& parameter) = 0;
+ virtual Maybe<RenderEffectParameter> getEffectScriptableParameter(String const& effectName, String const& parameterName) = 0;
+ virtual Maybe<VariantTypeIndex> getEffectScriptableParameterType(String const& effectName, String const& parameterName) = 0;
virtual void setEffectTexture(String const& textureName, ImageView const& image) = 0;
virtual bool switchEffectConfig(String const& name) = 0;
diff --git a/source/application/StarRenderer_opengl.cpp b/source/application/StarRenderer_opengl.cpp
index 9d0d717..ceb945d 100644
--- a/source/application/StarRenderer_opengl.cpp
+++ b/source/application/StarRenderer_opengl.cpp
@@ -308,21 +308,39 @@ void OpenGlRenderer::loadEffectConfig(String const& name, Json const& effectConf
throw RendererException::format("Unrecognized effect parameter type '{}'", type);
}
- effect.parameters[p.first] = effectParameter;
-
- if (Json def = p.second.get("default", {})) {
- if (type == "bool") {
- setEffectParameter(p.first, def.toBool());
- } else if (type == "int") {
- setEffectParameter(p.first, (int)def.toInt());
- } else if (type == "float") {
- setEffectParameter(p.first, def.toFloat());
- } else if (type == "vec2") {
- setEffectParameter(p.first, jsonToVec2F(def));
- } else if (type == "vec3") {
- setEffectParameter(p.first, jsonToVec3F(def));
- } else if (type == "vec4") {
- setEffectParameter(p.first, jsonToVec4F(def));
+ if (p.second.getBool("scriptable",false)) {
+ if (Json def = p.second.get("default", {})) {
+ if (type == "bool") {
+ effectParameter.parameterValue = (RenderEffectParameter)def.toBool();
+ } else if (type == "int") {
+ effectParameter.parameterValue = (RenderEffectParameter)(int)def.toInt();
+ } else if (type == "float") {
+ effectParameter.parameterValue = (RenderEffectParameter)def.toFloat();
+ } else if (type == "vec2") {
+ effectParameter.parameterValue = (RenderEffectParameter)jsonToVec2F(def);
+ } else if (type == "vec3") {
+ effectParameter.parameterValue = (RenderEffectParameter)jsonToVec3F(def);
+ } else if (type == "vec4") {
+ effectParameter.parameterValue = (RenderEffectParameter)jsonToVec4F(def);
+ }
+ }
+ effect.scriptables[p.first] = effectParameter;
+ } else {
+ effect.parameters[p.first] = effectParameter;
+ if (Json def = p.second.get("default", {})) {
+ if (type == "bool") {
+ setEffectParameter(p.first, def.toBool());
+ } else if (type == "int") {
+ setEffectParameter(p.first, (int)def.toInt());
+ } else if (type == "float") {
+ setEffectParameter(p.first, def.toFloat());
+ } else if (type == "vec2") {
+ setEffectParameter(p.first, jsonToVec2F(def));
+ } else if (type == "vec3") {
+ setEffectParameter(p.first, jsonToVec3F(def));
+ } else if (type == "vec4") {
+ setEffectParameter(p.first, jsonToVec4F(def));
+ }
}
}
}
@@ -384,6 +402,50 @@ void OpenGlRenderer::setEffectParameter(String const& parameterName, RenderEffec
ptr->parameterValue = value;
}
+void OpenGlRenderer::setEffectScriptableParameter(String const& effectName, String const& parameterName, RenderEffectParameter const& value) {
+ auto find = m_effects.find(effectName);
+ if (find == m_effects.end())
+ return;
+
+ Effect& effect = find->second;
+
+ auto ptr = effect.scriptables.ptr(parameterName);
+ if (!ptr || (ptr->parameterValue && *ptr->parameterValue == value))
+ return;
+
+ if (ptr->parameterType != value.typeIndex())
+ throw RendererException::format("OpenGlRenderer::setEffectScriptableParameter '{}' parameter type mismatch", parameterName);
+
+ ptr->parameterValue = value;
+}
+
+Maybe<RenderEffectParameter> OpenGlRenderer::getEffectScriptableParameter(String const& effectName, String const& parameterName) {
+ auto find = m_effects.find(effectName);
+ if (find == m_effects.end())
+ return {};
+
+ Effect& effect = find->second;
+
+ auto ptr = effect.scriptables.ptr(parameterName);
+ if (!ptr)
+ return {};
+
+ return ptr->parameterValue;
+}
+Maybe<VariantTypeIndex> OpenGlRenderer::getEffectScriptableParameterType(String const& effectName, String const& parameterName) {
+ auto find = m_effects.find(effectName);
+ if (find == m_effects.end())
+ return {};
+
+ Effect& effect = find->second;
+
+ auto ptr = effect.scriptables.ptr(parameterName);
+ if (!ptr)
+ return {};
+
+ return ptr->parameterType;
+}
+
void OpenGlRenderer::setEffectTexture(String const& textureName, ImageView const& image) {
auto ptr = m_currentEffect->textures.ptr(textureName);
if (!ptr)
@@ -1063,6 +1125,26 @@ void OpenGlRenderer::setupGlUniforms(Effect& effect, Vec2U screenSize) {
}
glUniform2f(m_screenSizeUniform, screenSize[0], screenSize[1]);
+
+ for (auto& param : effect.scriptables) {
+ auto ptr = &param.second;
+ auto mvalue = ptr->parameterValue;
+ if (mvalue) {
+ RenderEffectParameter value = mvalue.value();
+ if (auto v = value.ptr<bool>())
+ glUniform1i(ptr->parameterUniform, *v);
+ else if (auto v = value.ptr<int>())
+ glUniform1i(ptr->parameterUniform, *v);
+ else if (auto v = value.ptr<float>())
+ glUniform1f(ptr->parameterUniform, *v);
+ else if (auto v = value.ptr<Vec2F>())
+ glUniform2f(ptr->parameterUniform, (*v)[0], (*v)[1]);
+ else if (auto v = value.ptr<Vec3F>())
+ glUniform3f(ptr->parameterUniform, (*v)[0], (*v)[1], (*v)[2]);
+ else if (auto v = value.ptr<Vec4F>())
+ glUniform4f(ptr->parameterUniform, (*v)[0], (*v)[1], (*v)[2], (*v)[3]);
+ }
+ }
}
RefPtr<OpenGlRenderer::GlFrameBuffer> OpenGlRenderer::getGlFrameBuffer(String const& id) {
diff --git a/source/application/StarRenderer_opengl.hpp b/source/application/StarRenderer_opengl.hpp
index 36b8354..79e5400 100644
--- a/source/application/StarRenderer_opengl.hpp
+++ b/source/application/StarRenderer_opengl.hpp
@@ -25,6 +25,9 @@ public:
void loadEffectConfig(String const& name, Json const& effectConfig, StringMap<String> const& shaders) override;
void setEffectParameter(String const& parameterName, RenderEffectParameter const& parameter) override;
+ void setEffectScriptableParameter(String const& effectName, String const& parameterName, RenderEffectParameter const& parameter) override;
+ Maybe<RenderEffectParameter> getEffectScriptableParameter(String const& effectName, String const& parameterName) override;
+ Maybe<VariantTypeIndex> getEffectScriptableParameterType(String const& effectName, String const& parameterName) override;
void setEffectTexture(String const& textureName, ImageView const& image) override;
void setScissorRect(Maybe<RectI> const& scissorRect) override;
@@ -191,6 +194,7 @@ private:
GLuint program = 0;
Json config;
StringMap<EffectParameter> parameters;
+ StringMap<EffectParameter> scriptables; // scriptable parameters which can be changed when the effect is not loaded
StringMap<EffectTexture> textures;
StringMap<GLuint> attributes;
diff --git a/source/client/StarRenderingLuaBindings.cpp b/source/client/StarRenderingLuaBindings.cpp
index 4c9e7a2..39dc1a1 100644
--- a/source/client/StarRenderingLuaBindings.cpp
+++ b/source/client/StarRenderingLuaBindings.cpp
@@ -1,6 +1,8 @@
#include "StarRenderingLuaBindings.hpp"
+#include "StarJsonExtra.hpp"
#include "StarLuaConverters.hpp"
#include "StarClientApplication.hpp"
+#include "StarRenderer.hpp"
namespace Star {
@@ -11,8 +13,30 @@ LuaCallbacks LuaBindings::makeRenderingCallbacks(ClientApplication* app) {
callbacks.registerCallbackWithSignature<void, String, bool, Maybe<bool>>("setPostProcessGroupEnabled", bind(mem_fn(&ClientApplication::setPostProcessGroupEnabled), app, _1, _2, _3));
callbacks.registerCallbackWithSignature<bool, String>("postProcessGroupEnabled", bind(mem_fn(&ClientApplication::postProcessGroupEnabled), app, _1));
+
// not entirely necessary (root.assetJson can achieve the same purpose) but may as well
callbacks.registerCallbackWithSignature<Json>("postProcessGroups", bind(mem_fn(&ClientApplication::postProcessGroups), app));
+
+ // typedef Variant<float, int, Vec2F, Vec3F, Vec4F, bool> RenderEffectParameter;
+ // feel free to change this if there's a better way to do this
+ // specifically checks if the effect parameter is an int since Lua prefers converting the values to floats
+ callbacks.registerCallback("setEffectParameter", [app](String const& effectName, String const& effectParameter, RenderEffectParameter const& value) {
+ auto renderer = app->renderer();
+ auto mtype = renderer->getEffectScriptableParameterType(effectName, effectParameter);
+ if (mtype) {
+ auto type = mtype.value();
+ if (type == 1 && value.is<float>()) {
+ renderer->setEffectScriptableParameter(effectName, effectParameter, (int)value.get<float>());
+ } else {
+ renderer->setEffectScriptableParameter(effectName, effectParameter, value);
+ }
+ }
+ });
+
+ callbacks.registerCallback("getEffectParameter", [app](String const& effectName, String const& effectParameter) {
+ auto renderer = app->renderer();
+ return renderer->getEffectScriptableParameter(effectName, effectParameter);
+ });
return callbacks;
}
diff --git a/source/core/StarLuaConverters.hpp b/source/core/StarLuaConverters.hpp
index d9dfc67..c79cbdc 100644
--- a/source/core/StarLuaConverters.hpp
+++ b/source/core/StarLuaConverters.hpp
@@ -168,11 +168,11 @@ struct LuaConverter<Line<T, N>> {
template <typename FirstType, typename... RestTypes>
struct LuaConverter<Variant<FirstType, RestTypes...>> {
static LuaValue from(LuaEngine& engine, Variant<FirstType, RestTypes...> const& variant) {
- return variant.call([&engine](auto const& a) { return luaFrom(engine, a); });
+ return variant.call([&engine](auto const& a) { return engine.luaFrom(a); });
}
static LuaValue from(LuaEngine& engine, Variant<FirstType, RestTypes...>&& variant) {
- return variant.call([&engine](auto& a) { return luaFrom(engine, std::move(a)); });
+ return variant.call([&engine](auto& a) { return engine.luaFrom(std::move(a)); });
}
static Maybe<Variant<FirstType, RestTypes...>> to(LuaEngine& engine, LuaValue const& v) {
@@ -217,7 +217,7 @@ struct LuaConverter<MVariant<Types...>> {
static LuaValue from(LuaEngine& engine, MVariant<Types...> const& variant) {
LuaValue value;
variant.call([&value, &engine](auto const& a) {
- value = luaFrom(engine, a);
+ value = engine.luaFrom(a);
});
return value;
}
@@ -225,7 +225,7 @@ struct LuaConverter<MVariant<Types...>> {
static LuaValue from(LuaEngine& engine, MVariant<Types...>&& variant) {
LuaValue value;
variant.call([&value, &engine](auto& a) {
- value = luaFrom(engine, std::move(a));
+ value = engine.luaFrom(std::move(a));
});
return value;
}
diff --git a/source/windowing/StarScrollArea.cpp b/source/windowing/StarScrollArea.cpp
index f4cc140..775462a 100644
--- a/source/windowing/StarScrollArea.cpp
+++ b/source/windowing/StarScrollArea.cpp
@@ -384,7 +384,8 @@ bool ScrollArea::sendEvent(InputEvent const& event) {
return true;
}
-void ScrollArea::update(float) {
+void ScrollArea::update(float dt) {
+ Widget::update(dt);
if (!m_visible)
return;