Files
2026-09-26 16:32:40 +03:00

232 lines
4.1 KiB
Go

package input
import "aego/core/mathx"
type Button uint8
const (
MouseLeft Button = iota
MouseRight
MouseMiddle
MouseX1
MouseX2
)
const (
ButtonCount = 8
TextCapacity = 64
)
var buttonNames = [...]string{"left", "right", "middle", "x1", "x2"}
func (b Button) String() string {
if int(b) < len(buttonNames) {
return buttonNames[b]
}
return "other"
}
const (
flagDown uint8 = 1 << iota
flagPressed
flagReleased
flagRepeat
)
type KeyEvent struct {
Scan Scancode
Key Keycode
Mods Mods
Repeat bool
}
type MouseEvent struct {
Pos mathx.Vec2
Delta mathx.Vec2
Wheel mathx.Vec2
Button Button
}
type Frame struct {
Keys [ScancodeCount]uint8
Buttons [ButtonCount]uint8
MousePos mathx.Vec2
MouseDelta mathx.Vec2
Wheel mathx.Vec2
Mods Mods
Text [TextCapacity]byte
TextN uint8
}
type State struct {
f Frame
}
func (s *State) BeginFrame() {
for i, v := range s.f.Keys {
s.f.Keys[i] = v & flagDown
}
for i, v := range s.f.Buttons {
s.f.Buttons[i] = v & flagDown
}
s.f.MouseDelta = mathx.Vec2{}
s.f.Wheel = mathx.Vec2{}
s.f.TextN = 0
}
func (s *State) Reset() {
for i, v := range s.f.Keys {
if v&flagDown != 0 {
s.f.Keys[i] = (v &^ (flagDown | flagRepeat)) | flagReleased
}
}
for i, v := range s.f.Buttons {
if v&flagDown != 0 {
s.f.Buttons[i] = (v &^ flagDown) | flagReleased
}
}
s.f.MouseDelta = mathx.Vec2{}
s.f.Wheel = mathx.Vec2{}
s.f.Mods = 0
}
func (s *State) ApplyKeyDown(scan Scancode, key Keycode, mods Mods, repeat bool) {
s.f.Mods = mods
if !scan.Valid() {
return
}
if repeat {
s.f.Keys[scan] |= flagRepeat
return
}
apply(&s.f.Keys[scan], true)
}
func (s *State) KeyRepeated(k Scancode) bool {
return int(k) < ScancodeCount && s.f.Keys[k]&(flagPressed|flagRepeat) != 0
}
func (s *State) ApplyKeyUp(scan Scancode, key Keycode, mods Mods) {
s.f.Mods = mods
if !scan.Valid() {
return
}
apply(&s.f.Keys[scan], false)
}
func (s *State) ApplyMouseMove(pos, delta mathx.Vec2) {
s.f.MousePos = pos
s.f.MouseDelta = s.f.MouseDelta.Add(delta)
}
func (s *State) ApplyMouseDown(pos mathx.Vec2, b Button) {
s.f.MousePos = pos
if int(b) >= ButtonCount {
return
}
apply(&s.f.Buttons[b], true)
}
func (s *State) ApplyMouseUp(pos mathx.Vec2, b Button) {
s.f.MousePos = pos
if int(b) >= ButtonCount {
return
}
apply(&s.f.Buttons[b], false)
}
func (s *State) ApplyWheel(pos, wheel mathx.Vec2) {
s.f.MousePos = pos
s.f.Wheel = s.f.Wheel.Add(wheel)
}
func (s *State) ApplyText(text []byte) {
if s.f.TextN >= TextCapacity {
return
}
n := copy(s.f.Text[s.f.TextN:], text)
s.f.TextN += uint8(n)
}
func apply(flags *uint8, down bool) {
if down {
if *flags&flagDown == 0 {
*flags |= flagDown | flagPressed
}
return
}
if *flags&flagDown != 0 {
*flags = (*flags &^ flagDown) | flagReleased
}
}
func (s *State) KeyDown(k Scancode) bool {
return int(k) < ScancodeCount && s.f.Keys[k]&flagDown != 0
}
func (s *State) KeyPressed(k Scancode) bool {
return int(k) < ScancodeCount && s.f.Keys[k]&flagPressed != 0
}
func (s *State) KeyReleased(k Scancode) bool {
return int(k) < ScancodeCount && s.f.Keys[k]&flagReleased != 0
}
func (s *State) Mods() Mods {
return s.f.Mods
}
func (s *State) MousePos() mathx.Vec2 {
return s.f.MousePos
}
func (s *State) MouseDelta() mathx.Vec2 {
return s.f.MouseDelta
}
func (s *State) Wheel() mathx.Vec2 {
return s.f.Wheel
}
func (s *State) ButtonDown(b Button) bool {
return int(b) < ButtonCount && s.f.Buttons[b]&flagDown != 0
}
func (s *State) ButtonPressed(b Button) bool {
return int(b) < ButtonCount && s.f.Buttons[b]&flagPressed != 0
}
func (s *State) ButtonReleased(b Button) bool {
return int(b) < ButtonCount && s.f.Buttons[b]&flagReleased != 0
}
func (s *State) Text() []byte {
return s.f.Text[:s.f.TextN]
}
func (s *State) EachDown(fn func(Scancode)) {
for i, v := range s.f.Keys {
if v&flagDown != 0 {
fn(Scancode(i))
}
}
}
func (s *State) DownCount() int {
n := 0
for _, v := range s.f.Keys {
if v&flagDown != 0 {
n++
}
}
return n
}
func (s *State) Snapshot() Frame {
return s.f
}
func (s *State) Restore(f Frame) {
s.f = f
}