Touch editor: the panel gets out of the way by itself

The editor panel was a floating window pinned to the top of the screen, so
every button underneath it had to be uncovered by hand before it could be
touched. Dragging it was not an occasional adjustment, it was the price of
editing anything in the top half of the layout.

It now docks to the opposite half from whatever is selected: pick a button up
top and the panel goes to the bottom, pick one at the bottom and it returns.
Halves rather than real overlap maths, deliberately -- a panel that darts
around as rectangles graze each other is less predictable than one that is
simply never on the same side as the thing you are working on.

Manual dragging stays for anything unusual. The stored offset means "away
from the anchored edge" and so flips with the anchor; without that, a panel
the user had nudged down would be nudged straight off the bottom of the
screen the moment it docked there.
This commit is contained in:
jpolo1224
2026-08-24 10:37:36 -04:00
parent f2b092cb6e
commit 302a66a9bb
@@ -420,12 +420,34 @@ fun TouchControlsOverlay() {
val dxState = TouchControls.editorPanelDx(isLandscape)
val dyState = TouchControls.editorPanelDy(isLandscape)
val panelScale = TouchControls.editorPanelScale(isLandscape).floatValue
// ★ The panel moves ITSELF off whatever is being edited.
//
// It used to be a floating window pinned to the top, which meant every button under
// it had to be uncovered by hand before it could be touched -- "having to drag it
// around everywhere". Dragging is still there for anything unusual, but it should
// not be the price of editing a button in the top half of the screen.
//
// Halves rather than real overlap maths: the rule has to be predictable. A panel
// that darts around as rectangles graze each other is worse than one that is simply
// always on the opposite side from the thing you picked.
val selectedY = TouchControls.selectedButton.value?.let { id ->
layout.buttons.firstOrNull { it.id == id }?.yFrac
}
val dockBottom = selectedY != null && selectedY < 0.5f
Box(
Modifier
.align(Alignment.TopCenter)
.padding(top = 12.dp)
.align(if (dockBottom) Alignment.BottomCenter else Alignment.TopCenter)
.padding(top = if (dockBottom) 0.dp else 12.dp, bottom = if (dockBottom) 12.dp else 0.dp)
.offset {
IntOffset(dxState.floatValue.roundToInt(), dyState.floatValue.roundToInt())
// The stored offset means "away from the anchored edge", so it has to
// flip with the anchor -- otherwise a panel the user had nudged DOWN
// would be nudged straight off the bottom of the screen once it docked
// there.
IntOffset(
dxState.floatValue.roundToInt(),
(if (dockBottom) -dyState.floatValue else dyState.floatValue).roundToInt(),
)
},
) {
CompositionLocalProvider(