Hide structs in internal/ui

This commit is contained in:
Hajime Hoshi 2015-01-02 03:25:31 +09:00
parent a9e323d02c
commit 3d01084a2a
5 changed files with 70 additions and 51 deletions

View File

@ -23,24 +23,24 @@ import (
// IsKeyPressed returns a boolean indicating whether key is pressed. // IsKeyPressed returns a boolean indicating whether key is pressed.
func IsKeyPressed(key Key) bool { func IsKeyPressed(key Key) bool {
return ui.Current().Input().IsKeyPressed(ui.Key(key)) return ui.IsKeyPressed(ui.Key(key))
} }
// CursorPosition returns a position of a mouse cursor. // CursorPosition returns a position of a mouse cursor.
func CursorPosition() (x, y int) { func CursorPosition() (x, y int) {
return ui.Current().Input().CursorPosition() return ui.CursorPosition()
} }
// IsMouseButtonPressed returns a boolean indicating whether mouseButton is pressed. // IsMouseButtonPressed returns a boolean indicating whether mouseButton is pressed.
func IsMouseButtonPressed(mouseButton MouseButton) bool { func IsMouseButtonPressed(mouseButton MouseButton) bool {
return ui.Current().Input().IsMouseButtonPressed(ui.MouseButton(mouseButton)) return ui.IsMouseButtonPressed(ui.MouseButton(mouseButton))
} }
// NewImage returns an empty image. // NewImage returns an empty image.
func NewImage(width, height int, filter Filter) (*Image, error) { func NewImage(width, height int, filter Filter) (*Image, error) {
var innerImage *innerImage var innerImage *innerImage
var err error var err error
ui.Current().Use(func(c *opengl.Context) { ui.Use(func(c *opengl.Context) {
var texture *graphics.Texture var texture *graphics.Texture
texture, err = graphics.NewTexture(c, width, height, glFilter(c, filter)) texture, err = graphics.NewTexture(c, width, height, glFilter(c, filter))
if err != nil { if err != nil {
@ -52,14 +52,14 @@ func NewImage(width, height int, filter Filter) (*Image, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Image{ui: ui.Current(), inner: innerImage}, nil return &Image{inner: innerImage}, nil
} }
// NewImageFromImage creates a new image with the given image (img). // NewImageFromImage creates a new image with the given image (img).
func NewImageFromImage(img image.Image, filter Filter) (*Image, error) { func NewImageFromImage(img image.Image, filter Filter) (*Image, error) {
var innerImage *innerImage var innerImage *innerImage
var err error var err error
ui.Current().Use(func(c *opengl.Context) { ui.Use(func(c *opengl.Context) {
var texture *graphics.Texture var texture *graphics.Texture
texture, err = graphics.NewTextureFromImage(c, img, glFilter(c, filter)) texture, err = graphics.NewTextureFromImage(c, img, glFilter(c, filter))
if err != nil { if err != nil {
@ -70,5 +70,5 @@ func NewImageFromImage(img image.Image, filter Filter) (*Image, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Image{ui: ui.Current(), inner: innerImage}, nil return &Image{inner: innerImage}, nil
} }

View File

@ -103,7 +103,6 @@ func (t *textureQuads) Texture(i int) (u0, v0, u1, v1 float32) {
// The pixel format is alpha-premultiplied. // The pixel format is alpha-premultiplied.
// Image implements image.Image. // Image implements image.Image.
type Image struct { type Image struct {
ui *ui.UI
inner *innerImage inner *innerImage
pixels []uint8 pixels []uint8
} }
@ -116,7 +115,7 @@ func (i *Image) Size() (width, height int) {
// Clear resets the pixels of the image into 0. // Clear resets the pixels of the image into 0.
func (i *Image) Clear() (err error) { func (i *Image) Clear() (err error) {
i.pixels = nil i.pixels = nil
i.ui.Use(func(c *opengl.Context) { ui.Use(func(c *opengl.Context) {
err = i.inner.Clear(c) err = i.inner.Clear(c)
}) })
return return
@ -125,7 +124,7 @@ func (i *Image) Clear() (err error) {
// Fill fills the image with a solid color. // Fill fills the image with a solid color.
func (i *Image) Fill(clr color.Color) (err error) { func (i *Image) Fill(clr color.Color) (err error) {
i.pixels = nil i.pixels = nil
i.ui.Use(func(c *opengl.Context) { ui.Use(func(c *opengl.Context) {
err = i.inner.Fill(c, clr) err = i.inner.Fill(c, clr)
}) })
return return
@ -148,7 +147,7 @@ func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) {
func (i *Image) drawImage(image *innerImage, option *DrawImageOptions) (err error) { func (i *Image) drawImage(image *innerImage, option *DrawImageOptions) (err error) {
i.pixels = nil i.pixels = nil
i.ui.Use(func(c *opengl.Context) { ui.Use(func(c *opengl.Context) {
err = i.inner.drawImage(c, image, option) err = i.inner.drawImage(c, image, option)
}) })
return return
@ -170,7 +169,7 @@ func (i *Image) ColorModel() color.Model {
// This method loads pixels from GPU to VRAM if necessary. // This method loads pixels from GPU to VRAM if necessary.
func (i *Image) At(x, y int) color.Color { func (i *Image) At(x, y int) color.Color {
if i.pixels == nil { if i.pixels == nil {
i.ui.Use(func(c *opengl.Context) { ui.Use(func(c *opengl.Context) {
var err error var err error
i.pixels, err = i.inner.texture.Pixels(c) i.pixels, err = i.inner.texture.Pixels(c)
if err != nil { if err != nil {

View File

@ -39,22 +39,34 @@ const (
MouseButtonMax MouseButtonMax
) )
type Input struct { func IsKeyPressed(key Key) bool {
return current.input.isKeyPressed(key)
}
func IsMouseButtonPressed(button MouseButton) bool {
return current.input.isMouseButtonPressed(button)
}
func CursorPosition() (x, y int) {
return current.input.cursorPosition()
}
type input struct {
keyPressed [KeyMax]bool keyPressed [KeyMax]bool
mouseButtonPressed [MouseButtonMax]bool mouseButtonPressed [MouseButtonMax]bool
cursorX int cursorX int
cursorY int cursorY int
} }
func (i *Input) IsKeyPressed(key Key) bool { func (i *input) isKeyPressed(key Key) bool {
return i.keyPressed[key] return i.keyPressed[key]
} }
func (i *Input) IsMouseButtonPressed(button MouseButton) bool { func (i *input) isMouseButtonPressed(button MouseButton) bool {
return i.mouseButtonPressed[button] return i.mouseButtonPressed[button]
} }
func (i *Input) CursorPosition() (x, y int) { func (i *input) cursorPosition() (x, y int) {
return i.cursorX, i.cursorY return i.cursorX, i.cursorY
} }
@ -66,7 +78,7 @@ var glfwKeyCodeToKey = map[glfw.Key]Key{
glfw.KeyDown: KeyDown, glfw.KeyDown: KeyDown,
} }
func (i *Input) update(window *glfw.Window, scale int) { func (i *input) update(window *glfw.Window, scale int) {
for g, u := range glfwKeyCodeToKey { for g, u := range glfwKeyCodeToKey {
i.keyPressed[u] = window.GetKey(g) == glfw.Press i.keyPressed[u] = window.GetKey(g) == glfw.Press
} }

View File

@ -21,10 +21,35 @@ import (
"runtime" "runtime"
) )
var current *UI var current *ui
func Current() *UI { func Use(f func(*opengl.Context)) {
return current ch := make(chan struct{})
current.funcs <- func() {
defer close(ch)
f(current.glContext)
}
<-ch
}
func ActualScale() int {
return current.actualScale
}
func DoEvents() {
current.doEvents()
}
func Terminate() {
current.terminate()
}
func IsClosed() bool {
return current.isClosed()
}
func SwapBuffers() {
current.swapBuffers()
} }
func init() { func init() {
@ -44,7 +69,7 @@ func init() {
panic(err) panic(err)
} }
u := &UI{ u := &ui{
window: window, window: window,
funcs: make(chan func()), funcs: make(chan func()),
} }
@ -60,23 +85,23 @@ func init() {
current = u current = u
} }
type UI struct { type ui struct {
window *glfw.Window window *glfw.Window
scale int scale int
actualScale int actualScale int
glContext *opengl.Context glContext *opengl.Context
input Input input input
funcs chan func() funcs chan func()
} }
func New(width, height, scale int, title string) (*UI, error) { func Start(width, height, scale int, title string) error {
monitor, err := glfw.GetPrimaryMonitor() monitor, err := glfw.GetPrimaryMonitor()
if err != nil { if err != nil {
return nil, err return err
} }
videoMode, err := monitor.GetVideoMode() videoMode, err := monitor.GetVideoMode()
if err != nil { if err != nil {
return nil, err return err
} }
x := (videoMode.Width - width*scale) / 2 x := (videoMode.Width - width*scale) / 2
y := (videoMode.Height - height*scale) / 3 y := (videoMode.Height - height*scale) / 3
@ -111,39 +136,22 @@ func New(width, height, scale int, title string) (*UI, error) {
windowWidth, _ := window.GetFramebufferSize() windowWidth, _ := window.GetFramebufferSize()
ui.actualScale = windowWidth / width ui.actualScale = windowWidth / width
return ui, err return err
} }
func (u *UI) ActualScale() int { func (u *ui) doEvents() {
return u.actualScale
}
func (u *UI) DoEvents() {
glfw.PollEvents() glfw.PollEvents()
u.input.update(u.window, u.scale) u.input.update(u.window, u.scale)
} }
func (u *UI) Terminate() { func (u *ui) terminate() {
glfw.Terminate() glfw.Terminate()
} }
func (u *UI) IsClosed() bool { func (u *ui) isClosed() bool {
return u.window.ShouldClose() return u.window.ShouldClose()
} }
func (u *UI) SwapBuffers() { func (u *ui) swapBuffers() {
u.window.SwapBuffers() u.window.SwapBuffers()
} }
func (u *UI) Input() *Input {
return &u.input
}
func (u *UI) Use(f func(*opengl.Context)) {
ch := make(chan struct{})
u.funcs <- func() {
defer close(ch)
f(u.glContext)
}
<-ch
}

6
run.go
View File

@ -30,13 +30,13 @@ import (
// but this is not strictly guaranteed. // but this is not strictly guaranteed.
// If you need to care about time, you need to check current time every time f is called. // If you need to care about time, you need to check current time every time f is called.
func Run(f func(*Image) error, width, height, scale int, title string) error { func Run(f func(*Image) error, width, height, scale int, title string) error {
ui, err := ui.New(width, height, scale, title) if err := ui.Start(width, height, scale, title); err != nil {
if err != nil {
return err return err
} }
defer ui.Terminate() defer ui.Terminate()
var graphicsContext *graphicsContext var graphicsContext *graphicsContext
var err error
ui.Use(func(c *opengl.Context) { ui.Use(func(c *opengl.Context) {
graphicsContext, err = newGraphicsContext(c, width, height, ui.ActualScale()) graphicsContext, err = newGraphicsContext(c, width, height, ui.ActualScale())
}) })
@ -57,7 +57,7 @@ func Run(f func(*Image) error, width, height, scale int, title string) error {
if err != nil { if err != nil {
return err return err
} }
if err := f(&Image{ui: ui, inner: graphicsContext.screen}); err != nil { if err := f(&Image{inner: graphicsContext.screen}); err != nil {
return err return err
} }
ui.Use(func(*opengl.Context) { ui.Use(func(*opengl.Context) {