Joystick support in Fyne with glfw
This commit is contained in:
parent
17f1121980
commit
9395c2ffb3
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
fyne.io/fyne v1.3.3
|
fyne.io/fyne v1.3.3
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3
|
||||||
github.com/pkg/profile v1.4.0
|
github.com/pkg/profile v1.4.0
|
||||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
|
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
|
||||||
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
|
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gl/glfw/v3.3/glfw"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Apple 2 supports four paddles and 3 pushbuttons. The first two paddles are
|
||||||
|
the X, Y axis of the first joystick. The second two correspond the the second
|
||||||
|
joystick.
|
||||||
|
Button 0 is the primary button of joystick 0.
|
||||||
|
Button 1 is the secondary button of joystick 0 but also the primary button of
|
||||||
|
joystick 1.
|
||||||
|
Button 2 is the secondary button of Joystick 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: key as buttons as on the IIe and mouse as joystick
|
||||||
|
|
||||||
|
type joystickInfo struct {
|
||||||
|
present bool
|
||||||
|
name string
|
||||||
|
paddles [2]uint8
|
||||||
|
buttons [2]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type joysticks struct {
|
||||||
|
info [2]*joystickInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
const unplugged = uint8(255) // Max resistance when unplugged
|
||||||
|
|
||||||
|
func newJoysticks() *joysticks {
|
||||||
|
var j joysticks
|
||||||
|
return &j
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *joysticks) start() {
|
||||||
|
pool := time.NewTicker(time.Second / 50)
|
||||||
|
go func() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-pool.C:
|
||||||
|
j.info[0] = j.queryJoystick(glfw.Joystick1)
|
||||||
|
j.info[1] = j.queryJoystick(glfw.Joystick2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *joysticks) queryJoystick(joy glfw.Joystick) *joystickInfo {
|
||||||
|
if !joy.Present() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var info joystickInfo
|
||||||
|
info.name = joy.GetName()
|
||||||
|
buttons := joy.GetButtons()
|
||||||
|
for i, b := range buttons {
|
||||||
|
if b == glfw.Press {
|
||||||
|
info.buttons[i%2] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
axes := joy.GetAxes()
|
||||||
|
for i := 0; i < len(info.paddles); i++ {
|
||||||
|
info.paddles[i] = unplugged
|
||||||
|
if i < len(axes) {
|
||||||
|
v := uint16((axes[i] + 1.0) / 2.0 * 256.0)
|
||||||
|
if v > 255 {
|
||||||
|
v = 255
|
||||||
|
}
|
||||||
|
info.paddles[i] = uint8(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &info
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *joysticks) ReadButton(i int) bool {
|
||||||
|
var value bool
|
||||||
|
i0 := j.info[0]
|
||||||
|
i1 := j.info[1]
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
value = (i0 != nil) && i0.buttons[0]
|
||||||
|
case 1:
|
||||||
|
// It can be secondary of first or primary of second
|
||||||
|
value = ((i0 != nil) && i0.buttons[1]) ||
|
||||||
|
(i1 != nil) && i1.buttons[0]
|
||||||
|
case 2:
|
||||||
|
value = (i1 != nil) && i1.buttons[0]
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *joysticks) ReadPaddle(i int) (uint8, bool) {
|
||||||
|
var value = unplugged
|
||||||
|
info := j.info[i/2]
|
||||||
|
if info != nil {
|
||||||
|
value = info.paddles[i%2]
|
||||||
|
}
|
||||||
|
fmt.Printf("%v, %v, %v\n", i, j.info[0], value)
|
||||||
|
return value, value != unplugged
|
||||||
|
}
|
|
@ -19,7 +19,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type state struct {
|
type state struct {
|
||||||
a *izapple2.Apple2
|
a *izapple2.Apple2
|
||||||
|
app fyne.App
|
||||||
|
win fyne.Window
|
||||||
|
|
||||||
showPages bool
|
showPages bool
|
||||||
}
|
}
|
||||||
|
@ -39,9 +41,9 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func fyneRun(s *state) {
|
func fyneRun(s *state) {
|
||||||
app := app.New()
|
s.app = app.New()
|
||||||
// app.SetIcon(xxx)
|
// app.SetIcon(xxx)
|
||||||
window := app.NewWindow("iz-" + s.a.Name)
|
s.win = s.app.NewWindow("iz-" + s.a.Name)
|
||||||
// window.SetIcon(xxx)
|
// window.SetIcon(xxx)
|
||||||
|
|
||||||
bottom := widget.NewToolbar(
|
bottom := widget.NewToolbar(
|
||||||
|
@ -66,23 +68,25 @@ func fyneRun(s *state) {
|
||||||
theme.NewThemedResource(resourceLayersTripleSvg, nil), func() {
|
theme.NewThemedResource(resourceLayersTripleSvg, nil), func() {
|
||||||
s.showPages = !s.showPages
|
s.showPages = !s.showPages
|
||||||
if !s.showPages {
|
if !s.showPages {
|
||||||
window.SetTitle("iz-" + s.a.Name)
|
s.win.SetTitle("iz-" + s.a.Name)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
widget.NewToolbarAction(
|
widget.NewToolbarAction(
|
||||||
theme.NewThemedResource(resourceCameraSvg, nil), func() {
|
theme.NewThemedResource(resourceCameraSvg, nil), func() {
|
||||||
err := izapple2.SaveSnapshot(s.a, "snapshot.png")
|
err := izapple2.SaveSnapshot(s.a, "snapshot.png")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.SendNotification(fyne.NewNotification(window.Title(),
|
s.app.SendNotification(fyne.NewNotification(
|
||||||
|
s.win.Title(),
|
||||||
fmt.Sprintf("Error saving snapshoot: %v.\n.", err)))
|
fmt.Sprintf("Error saving snapshoot: %v.\n.", err)))
|
||||||
} else {
|
} else {
|
||||||
app.SendNotification(fyne.NewNotification(window.Title(),
|
s.app.SendNotification(fyne.NewNotification(
|
||||||
|
s.win.Title(),
|
||||||
"Saving snapshot on 'snapshot.png'"))
|
"Saving snapshot on 'snapshot.png'"))
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
widget.NewToolbarSpacer(),
|
widget.NewToolbarSpacer(),
|
||||||
widget.NewToolbarAction(theme.ViewFullScreenIcon(), func() {
|
widget.NewToolbarAction(theme.ViewFullScreenIcon(), func() {
|
||||||
window.SetFullScreen(!window.FullScreen())
|
s.win.SetFullScreen(!s.win.FullScreen())
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -92,10 +96,13 @@ func fyneRun(s *state) {
|
||||||
layout.NewBorderLayout(nil, bottom, nil, nil),
|
layout.NewBorderLayout(nil, bottom, nil, nil),
|
||||||
screen, bottom,
|
screen, bottom,
|
||||||
)
|
)
|
||||||
window.SetContent(container)
|
s.win.SetContent(container)
|
||||||
window.SetPadded(false)
|
s.win.SetPadded(false)
|
||||||
|
|
||||||
registerKeyboardEvents(s, window.Canvas())
|
registerKeyboardEvents(s)
|
||||||
|
j := newJoysticks()
|
||||||
|
j.start()
|
||||||
|
s.a.SetJoysticksProvider(j)
|
||||||
|
|
||||||
go s.a.Run()
|
go s.a.Run()
|
||||||
|
|
||||||
|
@ -111,7 +118,7 @@ func fyneRun(s *state) {
|
||||||
var img *image.RGBA
|
var img *image.RGBA
|
||||||
if s.showPages {
|
if s.showPages {
|
||||||
img = s.a.SnapshotParts()
|
img = s.a.SnapshotParts()
|
||||||
window.SetTitle(fmt.Sprintf("%v %v %vx%v", s.a.Name, s.a.VideoModeName(), img.Rect.Dx()/2, img.Rect.Dy()/2))
|
s.win.SetTitle(fmt.Sprintf("%v %v %vx%v", s.a.Name, s.a.VideoModeName(), img.Rect.Dx()/2, img.Rect.Dy()/2))
|
||||||
} else {
|
} else {
|
||||||
img = s.a.Snapshot()
|
img = s.a.Snapshot()
|
||||||
}
|
}
|
||||||
|
@ -122,19 +129,20 @@ func fyneRun(s *state) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
window.SetOnClosed(func() {
|
s.win.SetOnClosed(func() {
|
||||||
done <- true
|
done <- true
|
||||||
})
|
})
|
||||||
|
|
||||||
window.Show()
|
s.win.Show()
|
||||||
app.Run()
|
s.app.Run()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerKeyboardEvents(s *state, canvas fyne.Canvas) {
|
func registerKeyboardEvents(s *state) {
|
||||||
kp := newKeyboard(s)
|
kp := newKeyboard(s)
|
||||||
|
canvas := s.win.Canvas()
|
||||||
|
|
||||||
// Koyboard events
|
// Events
|
||||||
canvas.SetOnTypedKey(func(ke *fyne.KeyEvent) {
|
canvas.SetOnTypedKey(func(ke *fyne.KeyEvent) {
|
||||||
//fmt.Printf("Event: %v\n", ke.Name)
|
//fmt.Printf("Event: %v\n", ke.Name)
|
||||||
kp.putKey(ke)
|
kp.putKey(ke)
|
||||||
|
|
Loading…
Reference in New Issue