aboutsummaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
Diffstat (limited to 'win')
-rw-r--r--win/events.go89
-rw-r--r--win/win.go358
2 files changed, 0 insertions, 447 deletions
diff --git a/win/events.go b/win/events.go
deleted file mode 100644
index 90fab52..0000000
--- a/win/events.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package win
-
-import (
- "fmt"
- "image"
-)
-
-// Button indicates a mouse button in an event.
-type Button string
-
-// List of all mouse buttons.
-const (
- ButtonLeft Button = "left"
- ButtonRight Button = "right"
- ButtonMiddle Button = "middle"
-)
-
-// Key indicates a keyboard key in an event.
-type Key string
-
-// List of all keyboard keys.
-const (
- KeyLeft Key = "left"
- KeyRight Key = "right"
- KeyUp Key = "up"
- KeyDown Key = "down"
- KeyEscape Key = "escape"
- KeySpace Key = "space"
- KeyBackspace Key = "backspace"
- KeyDelete Key = "delete"
- KeyEnter Key = "enter"
- KeyTab Key = "tab"
- KeyHome Key = "home"
- KeyEnd Key = "end"
- KeyPageUp Key = "pageup"
- KeyPageDown Key = "pagedown"
- KeyShift Key = "shift"
- KeyCtrl Key = "ctrl"
- KeyAlt Key = "alt"
-)
-
-type (
- // WiClose is an event that happens when the user presses the close button on the window.
- WiClose struct{}
-
- // MoMove is an event that happens when the mouse gets moved across the window.
- MoMove struct{ image.Point }
-
- // MoDown is an event that happens when a mouse button gets pressed.
- MoDown struct {
- image.Point
- Button Button
- }
-
- // MoUp is an event that happens when a mouse button gets released.
- MoUp struct {
- image.Point
- Button Button
- }
-
- // MoScroll is an event that happens on scrolling the mouse.
- //
- // The Point field tells the amount scrolled in each direction.
- MoScroll struct{ image.Point }
-
- // KbType is an event that happens when a Unicode character gets typed on the keyboard.
- KbType struct{ Rune rune }
-
- // KbDown is an event that happens when a key on the keyboard gets pressed.
- KbDown struct{ Key Key }
-
- // KbUp is an event that happens when a key on the keyboard gets released.
- KbUp struct{ Key Key }
-
- // KbRepeat is an event that happens when a key on the keyboard gets repeated.
- //
- // This happens when its held down for some time.
- KbRepeat struct{ Key Key }
-)
-
-func (wc WiClose) String() string { return "wi/close" }
-func (mm MoMove) String() string { return fmt.Sprintf("mo/move/%d/%d", mm.X, mm.Y) }
-func (md MoDown) String() string { return fmt.Sprintf("mo/down/%d/%d/%s", md.X, md.Y, md.Button) }
-func (mu MoUp) String() string { return fmt.Sprintf("mo/up/%d/%d/%s", mu.X, mu.Y, mu.Button) }
-func (ms MoScroll) String() string { return fmt.Sprintf("mo/scroll/%d/%d", ms.X, ms.Y) }
-func (kt KbType) String() string { return fmt.Sprintf("kb/type/%d", kt.Rune) }
-func (kd KbDown) String() string { return fmt.Sprintf("kb/down/%s", kd.Key) }
-func (ku KbUp) String() string { return fmt.Sprintf("kb/up/%s", ku.Key) }
-func (kr KbRepeat) String() string { return fmt.Sprintf("kb/repeat/%s", kr.Key) }
diff --git a/win/win.go b/win/win.go
deleted file mode 100644
index 1741549..0000000
--- a/win/win.go
+++ /dev/null
@@ -1,358 +0,0 @@
-package win
-
-import (
- "image"
- "image/draw"
- "runtime"
- "time"
- "unsafe"
-
- "github.com/faiface/gui"
- "github.com/faiface/mainthread"
- "github.com/go-gl/gl/v2.1/gl"
- "github.com/go-gl/glfw/v3.2/glfw"
-)
-
-// Option is a functional option to the window constructor New.
-type Option func(*options)
-
-type options struct {
- title string
- width, height int
- resizable bool
- borderless bool
- maximized bool
-}
-
-// Title option sets the title (caption) of the window.
-func Title(title string) Option {
- return func(o *options) {
- o.title = title
- }
-}
-
-// Size option sets the width and height of the window.
-func Size(width, height int) Option {
- return func(o *options) {
- o.width = width
- o.height = height
- }
-}
-
-// Resizable option makes the window resizable by the user.
-func Resizable() Option {
- return func(o *options) {
- o.resizable = true
- }
-}
-
-// Borderless option makes the window borderless.
-func Borderless() Option {
- return func(o *options) {
- o.borderless = true
- }
-}
-
-// Maximized option makes the window start maximized.
-func Maximized() Option {
- return func(o *options) {
- o.maximized = true
- }
-}
-
-// New creates a new window with all the supplied options.
-//
-// The default title is empty and the default size is 640x480.
-func New(opts ...Option) (*Win, error) {
- o := options{
- title: "",
- width: 640,
- height: 480,
- resizable: false,
- borderless: false,
- maximized: false,
- }
- for _, opt := range opts {
- opt(&o)
- }
-
- eventsOut, eventsIn := gui.MakeEventsChan()
-
- w := &Win{
- eventsOut: eventsOut,
- eventsIn: eventsIn,
- draw: make(chan func(draw.Image) image.Rectangle),
- newSize: make(chan image.Rectangle),
- finish: make(chan struct{}),
- }
-
- var err error
- mainthread.Call(func() {
- w.w, err = makeGLFWWin(&o)
- })
- if err != nil {
- return nil, err
- }
-
- mainthread.Call(func() {
- // hiDPI hack
- width, _ := w.w.GetFramebufferSize()
- w.ratio = width / o.width
- if w.ratio < 1 {
- w.ratio = 1
- }
- if w.ratio != 1 {
- o.width /= w.ratio
- o.height /= w.ratio
- }
- w.w.Destroy()
- w.w, err = makeGLFWWin(&o)
- })
- if err != nil {
- return nil, err
- }
-
- bounds := image.Rect(0, 0, o.width*w.ratio, o.height*w.ratio)
- w.img = image.NewRGBA(bounds)
-
- go func() {
- runtime.LockOSThread()
- w.openGLThread()
- }()
-
- mainthread.CallNonBlock(w.eventThread)
-
- return w, nil
-}
-
-func makeGLFWWin(o *options) (*glfw.Window, error) {
- err := glfw.Init()
- if err != nil {
- return nil, err
- }
- glfw.WindowHint(glfw.DoubleBuffer, glfw.False)
- if o.resizable {
- glfw.WindowHint(glfw.Resizable, glfw.True)
- } else {
- glfw.WindowHint(glfw.Resizable, glfw.False)
- }
- if o.borderless {
- glfw.WindowHint(glfw.Decorated, glfw.False)
- }
- if o.maximized {
- glfw.WindowHint(glfw.Maximized, glfw.True)
- }
- w, err := glfw.CreateWindow(o.width, o.height, o.title, nil, nil)
- if err != nil {
- return nil, err
- }
- if o.maximized {
- o.width, o.height = w.GetFramebufferSize() // set o.width and o.height to the window size due to the window being maximized
- }
- return w, nil
-}
-
-// Win is an Env that handles an actual graphical window.
-//
-// It receives its events from the OS and it draws to the surface of the window.
-//
-// Warning: only one window can be open at a time. This will be fixed.
-type Win struct {
- eventsOut <-chan gui.Event
- eventsIn chan<- gui.Event
- draw chan func(draw.Image) image.Rectangle
-
- newSize chan image.Rectangle
- finish chan struct{}
-
- w *glfw.Window
- img *image.RGBA
- ratio int
-}
-
-// Events returns the events channel of the window.
-func (w *Win) Events() <-chan gui.Event { return w.eventsOut }
-
-// Draw returns the draw channel of the window.
-func (w *Win) Draw() chan<- func(draw.Image) image.Rectangle { return w.draw }
-
-var buttons = map[glfw.MouseButton]Button{
- glfw.MouseButtonLeft: ButtonLeft,
- glfw.MouseButtonRight: ButtonRight,
- glfw.MouseButtonMiddle: ButtonMiddle,
-}
-
-var keys = map[glfw.Key]Key{
- glfw.KeyLeft: KeyLeft,
- glfw.KeyRight: KeyRight,
- glfw.KeyUp: KeyUp,
- glfw.KeyDown: KeyDown,
- glfw.KeyEscape: KeyEscape,
- glfw.KeySpace: KeySpace,
- glfw.KeyBackspace: KeyBackspace,
- glfw.KeyDelete: KeyDelete,
- glfw.KeyEnter: KeyEnter,
- glfw.KeyTab: KeyTab,
- glfw.KeyHome: KeyHome,
- glfw.KeyEnd: KeyEnd,
- glfw.KeyPageUp: KeyPageUp,
- glfw.KeyPageDown: KeyPageDown,
- glfw.KeyLeftShift: KeyShift,
- glfw.KeyRightShift: KeyShift,
- glfw.KeyLeftControl: KeyCtrl,
- glfw.KeyRightControl: KeyCtrl,
- glfw.KeyLeftAlt: KeyAlt,
- glfw.KeyRightAlt: KeyAlt,
-}
-
-func (w *Win) eventThread() {
- var moX, moY int
-
- w.w.SetCursorPosCallback(func(_ *glfw.Window, x, y float64) {
- moX, moY = int(x), int(y)
- w.eventsIn <- MoMove{image.Pt(moX*w.ratio, moY*w.ratio)}
- })
-
- w.w.SetMouseButtonCallback(func(_ *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
- b, ok := buttons[button]
- if !ok {
- return
- }
- switch action {
- case glfw.Press:
- w.eventsIn <- MoDown{image.Pt(moX*w.ratio, moY*w.ratio), b}
- case glfw.Release:
- w.eventsIn <- MoUp{image.Pt(moX*w.ratio, moY*w.ratio), b}
- }
- })
-
- w.w.SetScrollCallback(func(_ *glfw.Window, xoff, yoff float64) {
- w.eventsIn <- MoScroll{image.Pt(int(xoff), int(yoff))}
- })
-
- w.w.SetCharCallback(func(_ *glfw.Window, r rune) {
- w.eventsIn <- KbType{r}
- })
-
- w.w.SetKeyCallback(func(_ *glfw.Window, key glfw.Key, _ int, action glfw.Action, _ glfw.ModifierKey) {
- k, ok := keys[key]
- if !ok {
- return
- }
- switch action {
- case glfw.Press:
- w.eventsIn <- KbDown{k}
- case glfw.Release:
- w.eventsIn <- KbUp{k}
- case glfw.Repeat:
- w.eventsIn <- KbRepeat{k}
- }
- })
-
- w.w.SetFramebufferSizeCallback(func(_ *glfw.Window, width, height int) {
- r := image.Rect(0, 0, width, height)
- w.newSize <- r
- w.eventsIn <- gui.Resize{Rectangle: r}
- })
-
- w.w.SetCloseCallback(func(_ *glfw.Window) {
- w.eventsIn <- WiClose{}
- })
-
- r := w.img.Bounds()
- w.eventsIn <- gui.Resize{Rectangle: r}
-
- for {
- select {
- case <-w.finish:
- close(w.eventsIn)
- w.w.Destroy()
- return
- default:
- glfw.WaitEventsTimeout(1.0 / 30)
- }
- }
-}
-
-func (w *Win) openGLThread() {
- w.w.MakeContextCurrent()
- gl.Init()
-
- w.openGLFlush(w.img.Bounds())
-
-loop:
- for {
- var totalR image.Rectangle
-
- select {
- case r := <-w.newSize:
- img := image.NewRGBA(r)
- draw.Draw(img, w.img.Bounds(), w.img, w.img.Bounds().Min, draw.Src)
- w.img = img
- totalR = totalR.Union(r)
-
- case d, ok := <-w.draw:
- if !ok {
- close(w.finish)
- return
- }
- r := d(w.img)
- totalR = totalR.Union(r)
- }
-
- for {
- select {
- case <-time.After(time.Second / 960):
- w.openGLFlush(totalR)
- totalR = image.ZR
- continue loop
-
- case r := <-w.newSize:
- img := image.NewRGBA(r)
- draw.Draw(img, w.img.Bounds(), w.img, w.img.Bounds().Min, draw.Src)
- w.img = img
- totalR = totalR.Union(r)
-
- case d, ok := <-w.draw:
- if !ok {
- close(w.finish)
- return
- }
- r := d(w.img)
- totalR = totalR.Union(r)
- }
- }
- }
-}
-
-func (w *Win) openGLFlush(r image.Rectangle) {
- bounds := w.img.Bounds()
- r = r.Intersect(bounds)
- if r.Empty() {
- return
- }
-
- tmp := image.NewRGBA(r)
- draw.Draw(tmp, r, w.img, r.Min, draw.Src)
-
- gl.DrawBuffer(gl.FRONT)
- gl.Viewport(
- int32(bounds.Min.X),
- int32(bounds.Min.Y),
- int32(bounds.Dx()),
- int32(bounds.Dy()),
- )
- gl.RasterPos2d(
- -1+2*float64(r.Min.X)/float64(bounds.Dx()),
- +1-2*float64(r.Min.Y)/float64(bounds.Dy()),
- )
- gl.PixelZoom(1, -1)
- gl.DrawPixels(
- int32(r.Dx()),
- int32(r.Dy()),
- gl.RGBA,
- gl.UNSIGNED_BYTE,
- unsafe.Pointer(&tmp.Pix[0]),
- )
- gl.Flush()
-}