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 } // 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 } } // 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, } 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 { 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, o.height) 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) } w, err := glfw.CreateWindow(o.width, o.height, o.title, nil, nil) if err != nil { return nil, err } 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. // // Here are all kinds of events that a window can produce, along with descriptions. // Things enclosed in <> are values that are filled in. // // resize// Window resized to w x h. // wi/close Window close button pressed. // mo/move// Mouse moved to (x, y). // mo/down///