Add input components 086-105; park focus off disabled controls
This commit is contained in:
34 files changed
+3058
-43
No files matched your search
@@ -0,0 +1,85 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
type JoystickOptions struct {
|
||||
Disabled bool
|
||||
}
|
||||
|
||||
type JoystickResult struct {
|
||||
Element *ui.Element
|
||||
// X and Y are in −1…1; Y grows downward.
|
||||
X, Y float64
|
||||
Moved bool
|
||||
}
|
||||
|
||||
type stickKey struct{}
|
||||
|
||||
// stick is the knob and its last key nudge.
|
||||
type stick struct {
|
||||
x, y float64
|
||||
key time.Time
|
||||
}
|
||||
|
||||
const (
|
||||
stickSize = 40
|
||||
// stickReach is how far the knob travels, in dots.
|
||||
stickReach = 12
|
||||
)
|
||||
|
||||
// Joystick drags a knob in a ring; arrows nudge it.
|
||||
func Joystick(c *ui.Context, text string, o JoystickOptions) JoystickResult {
|
||||
k := pixel.K(c)
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element {
|
||||
return ui.Box(c).Focusable().Role(ui.RoleGroup).Label(text).Disabled(o.Disabled)
|
||||
})
|
||||
s := ui.Local(base, stickKey{}, func() stick { return stick{} })
|
||||
ox, oy, now := s.x, s.y, k.Now()
|
||||
for _, m := range []struct {
|
||||
key ui.Key
|
||||
dx, dy float64
|
||||
}{{ui.KeyLeft, -0.25, 0}, {ui.KeyRight, 0.25, 0}, {ui.KeyUp, 0, -0.25}, {ui.KeyDown, 0, 0.25}} {
|
||||
if base.Shortcut(0, m.key) {
|
||||
s.x, s.y, s.key = s.x+m.dx, s.y+m.dy, now
|
||||
}
|
||||
}
|
||||
_, _, held := base.Dragged()
|
||||
switch {
|
||||
case held && !o.Disabled:
|
||||
px, py, _ := base.PointerPosition()
|
||||
s.x = (float64(px/k.Dot()) - stickSize/2) / stickReach
|
||||
s.y = (float64(py/k.Dot()) - stickSize/2) / stickReach
|
||||
s.key = time.Time{}
|
||||
case now.Sub(s.key) > repeatGap:
|
||||
s.x, s.y = 0, 0
|
||||
default:
|
||||
k.Tick(c, 10)
|
||||
}
|
||||
if l := math.Hypot(s.x, s.y); l > 1 {
|
||||
s.x, s.y = s.x/l, s.y/l
|
||||
}
|
||||
base.Description(fmt.Sprintf("%.2f, %.2f", s.x, s.y))
|
||||
x, y := stickSize/2+int(math.Round(s.x*stickReach)), stickSize/2+int(math.Round(s.y*stickReach))
|
||||
shell.Size(k.D(stickSize), k.D(stickSize)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
const m = stickSize / 2
|
||||
g.Disc(m, m, m-1, pixel.Edge)
|
||||
g.Disc(m, m, m-2, pixel.Well)
|
||||
g.Dither(m-2, 4, 4, stickSize-8, pixel.Well, pixel.Shade, 4)
|
||||
g.Dither(4, m-2, stickSize-8, 4, pixel.Well, pixel.Shade, 4)
|
||||
g.Disc(x+1, y+1, 7, pixel.Shade)
|
||||
g.Disc(x, y, 7, pixel.Edge)
|
||||
g.Disc(x, y, 6, pixel.Accent)
|
||||
g.Disc(x-2, y-2, 2, pixel.AccentLit)
|
||||
finish(g, st)
|
||||
})
|
||||
return JoystickResult{Element: shell, X: s.x, Y: s.y, Moved: s.x != ox || s.y != oy}
|
||||
}
|
||||
Reference in new issue
Block a user