2018-03-18 20:41:17 +00:00
|
|
|
package ui
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
|
2019-12-29 15:38:49 +00:00
|
|
|
"github.com/hajimehoshi/ebiten"
|
2019-12-29 17:30:21 +00:00
|
|
|
"github.com/hajimehoshi/ebiten/inpututil"
|
2018-03-18 20:41:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
winX = flag.Int("win-x", 1280, "width of the view-map window")
|
|
|
|
winY = flag.Int("win-y", 1024, "height of the view-map window")
|
|
|
|
)
|
|
|
|
|
|
|
|
type Window struct {
|
2019-12-29 17:30:21 +00:00
|
|
|
Title string
|
|
|
|
KeyUpHandlers map[ebiten.Key]func()
|
|
|
|
MouseWheelHandler func(float64, float64)
|
2019-12-29 15:38:49 +00:00
|
|
|
|
|
|
|
// User-provided update actions
|
|
|
|
updateFn func() error
|
|
|
|
drawFn func(*ebiten.Image) error
|
2018-03-18 20:41:17 +00:00
|
|
|
}
|
|
|
|
|
2019-12-29 15:38:49 +00:00
|
|
|
// 0,0 is the *top left* of the window
|
2018-03-18 20:41:17 +00:00
|
|
|
//
|
2019-12-29 15:38:49 +00:00
|
|
|
// ebiten assumes a single window, so only call this once...
|
2018-03-18 20:41:17 +00:00
|
|
|
func NewWindow(title string) (*Window, error) {
|
2019-12-29 15:38:49 +00:00
|
|
|
return &Window{
|
2019-12-29 17:30:21 +00:00
|
|
|
Title: title,
|
|
|
|
KeyUpHandlers: make(map[ebiten.Key]func()),
|
2019-12-29 15:38:49 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-12-29 17:30:21 +00:00
|
|
|
// TODO: multiple handlers for the same key?
|
2019-12-29 15:38:49 +00:00
|
|
|
func (w *Window) OnKeyUp(key ebiten.Key, f func()) {
|
2019-12-29 17:30:21 +00:00
|
|
|
w.KeyUpHandlers[key] = f
|
|
|
|
}
|
2019-12-29 15:38:49 +00:00
|
|
|
|
2019-12-29 17:30:21 +00:00
|
|
|
func (w *Window) OnMouseWheel(f func(x, y float64)) {
|
|
|
|
w.MouseWheelHandler = f
|
2019-12-29 15:38:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (w *Window) run(screen *ebiten.Image) error {
|
|
|
|
if err := w.updateFn(); err != nil {
|
|
|
|
return err
|
2018-03-18 20:41:17 +00:00
|
|
|
}
|
|
|
|
|
2019-12-29 15:38:49 +00:00
|
|
|
// Process keys
|
2019-12-29 17:30:21 +00:00
|
|
|
// TODO: efficient set operations
|
|
|
|
|
|
|
|
for key, cb := range w.KeyUpHandlers {
|
|
|
|
if inpututil.IsKeyJustReleased(key) {
|
|
|
|
cb()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if w.MouseWheelHandler != nil {
|
|
|
|
x, y := ebiten.Wheel()
|
|
|
|
if x != 0 || y != 0 {
|
|
|
|
w.MouseWheelHandler(x, y)
|
|
|
|
}
|
|
|
|
}
|
2019-12-29 15:38:49 +00:00
|
|
|
|
|
|
|
if !ebiten.IsDrawingSkipped() {
|
|
|
|
if err := w.drawFn(screen); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-03-18 20:41:17 +00:00
|
|
|
}
|
|
|
|
|
2019-12-29 15:38:49 +00:00
|
|
|
return nil
|
2018-03-18 20:41:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: a stop or other cancellation mechanism
|
2019-12-29 15:38:49 +00:00
|
|
|
//
|
|
|
|
// Note that this must be called on the main OS thread
|
|
|
|
func (w *Window) Run(updateFn func() error, drawFn func(*ebiten.Image) error) error {
|
|
|
|
w.updateFn = updateFn
|
|
|
|
w.drawFn = drawFn
|
|
|
|
|
|
|
|
return ebiten.Run(w.run, *winX, *winY, 1, w.Title)
|
2018-03-18 20:41:17 +00:00
|
|
|
}
|