fix(qt): honour log_scale from zero, and declare soft maxima explicitly - #57
Merged
Conversation
Two slider fixes, both in the same constructor. Closes #55. The industrial slider did implement a log mapping, but threw it away whenever the minimum sat at or below the log floor. A minimum of zero is the common case rather than the exotic one, so in practice a log attribute drew and dragged as a linear one and nothing said why. Stock's SliderFloat has always handled this by clamping the log domain to an epsilon rather than bailing out, so do the same here: floor every endpoint, not just the value, and decline only when the range is genuinely unbounded and there is no span to map. from_norm snaps the bottom of the rail back to the real minimum, so a rail declared from zero still reaches zero rather than bottoming out at the floor. The second one is a defect in #56 that I should not have let through. Letting a parameter accept a typed value above its drag range was keyed off a maximum of exactly 64, with no comment. The parameters that actually declare a maximum of 64 are Islands at 1..64 and n_vertices at 3..64, where the 64 is a hard cap, so all of them silently started accepting any number typed into them. It is a per attribute declaration now, ui.drag_max: the rail spans to it and typing goes to constraints::max. Absent, the rail spans to the real maximum and typing is bounded by the same value, which is what every attribute did before any of this. LinkedSliders forwards it, and log_scale, to its two axes, so a linked pair cannot behave differently from the single row beside it. Nothing in Hesiod sets ui.drag_max yet, so this restores the hard cap on Islands and n_vertices immediately and Spatial Frequency opts in separately. test_slider_mapping drives the log case by pressing the same point on a log rail and a linear one and comparing: 56.59 linear against 0.03 log on the same 0..100 range. It also covers the soft maximum both ways, typing past the rail and dragging that must not.
This was referenced Sep 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
two slider fixes, both in the same constructor.
closes #55. the industrial slider did have a log mapping, it just threw it away
whenever the minimum was at or below the log floor. min of 0 is the normal case
not the weird one, so in practice a log attribute drew and dragged as a linear
one and nothing told you why. stock's SliderFloat has always handled this by
clamping the log domain to an epsilon instead of bailing, so it does the same
now: floor every endpoint rather than just the value, and only decline when the
range is actually unbounded and theres no span to map at all. from_norm snaps
the bottom back to the real minimum so a rail declared from 0 still reaches 0
rather than stopping at 1e-6.
second one is a defect i let through in #56, sorry. the "type a value above the
drag range" thing was keyed off max being exactly 64, with no comment. the
parameters that actually declare max 64 are Islands at 1..64 and n_vertices at
3..64, where 64 is a hard cap, so all of those quietly started accepting any
number you typed at them.
its a per attribute declaration now, ui.drag_max. the rail spans to it and
typing goes to constraints::max. absent, the rail spans to the real max and
typing is bounded by the same thing, which is what everything did before any of
this. LinkedSliders forwards it and log_scale down to its two axes so a linked
pair cant end up behaving differently to the single row next to it.
nothing in hesiod sets ui.drag_max yet, so this puts the hard cap back on
Islands and n_vertices straight away, and spatial frequency opts in separately
on the hesiod side.
test_slider_mapping drives the log case by pressing the same point on a log rail
and a linear one and comparing, 56.59 vs 0.03 on the same 0..100 range. it also
covers the soft max both directions, typing past the rail and dragging that must
not. all four suites pass.