-
Notifications
You must be signed in to change notification settings - Fork 382
Description
I'm using RmlUi 6.1.
I am attempting to make a slider with a minimum/maximum that is provided by the data model. The RML:
<input type="range" name="max_players" data-value="selected_max_players"
data-attr-min="min_players" data-attr-max="max_players" step="1" kex-menu-nav />The code:
template<typename T>
bool BindAddress(Rml::DataModelConstructor &cCtor, std::string_view strName, T *pAddr)
{
return cCtor.BindFunc(
Rml::String{strName}, //
[pAddr](Rml::Variant &v) { v = *pAddr; }, //
[pAddr](const Rml::Variant &v) { *pAddr = v.Get<T>(); });
}
// In the binding function...
BindAddress(ctor, "min_players", &this->m_iMinPlayers);
BindAddress(ctor, "max_players", &this->m_iMaxPlayers);
BindAddress(ctor, "selected_max_players", &this->m_iSelectedMaxPlayers);However, when I open the page with the range input, the minimum and maximum values are correct, but the value itself is set to 2. If I get rid of the data-attr-min/data-attr-max the value is set correctly.
I think I know why this is happening. When DataViewAttribute::Update is called, the attributes are set one at a time. When the code hits InputTypeRange::OnAttributeChange it turns out that the first thing that gets changed is min, which calls this method:
void WidgetSlider::SetMinValue(float _min_value)
{
if (_min_value != min_value)
{
min_value = _min_value;
SetBarPosition(SetValueInternal(value, false));
}
}The default value of a range input is 0, so it gets clamped to 2, which in turn dispatches a EventId::Change event, which sets the actual value to 2. This blows up whatever value was seeded in the model ahead of time.
I believe this is due to the way data views work. It does updates one at a time, instead of all at once, thus if you have multiple views on a single element, and changing one value observed by the data model mutates something else touched by the data model, things go sideways.
It seems like the cromulent thing to do would be to queue all of the changes for a given element, then execute the changes all in one go.