backup before reinstall
This commit is contained in:
parent
69032cdcf3
commit
cafda2cfae
209
graphics.go
209
graphics.go
|
@ -9,72 +9,6 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Drawer is anything that can be drawn. It's by no means a drawer inside your table.
|
|
||||||
//
|
|
||||||
// Drawer consists of a single methods: Draw. Draw methods takes any number of Transform
|
|
||||||
// arguments. It applies these transforms in the reverse order and finally draws something
|
|
||||||
// transformed by these transforms.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// // object is a drawer
|
|
||||||
// object.Draw(pixel.Position(pixel.V(100, 100).Rotate(math.Pi / 2)))
|
|
||||||
// camera := pixel.Camera(pixel.V(0, 0), pixel.V(500, 500), pixel.V(window.Size()))
|
|
||||||
// object.Draw(camera, pixel.Position(0).Scale(0.5))
|
|
||||||
type Drawer interface {
|
|
||||||
Draw(t ...Transform)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Group is used to effeciently handle a collection of objects with a common parent. Usually many
|
|
||||||
// objects share a parent, using a group can significantly increase performance in these cases.
|
|
||||||
//
|
|
||||||
// To use a group, first, create a group and as it's parent use the common parent of the
|
|
||||||
// collection of objects:
|
|
||||||
//
|
|
||||||
// group := pixel.NewGroup(commonParent)
|
|
||||||
//
|
|
||||||
// Then, when creating the objects, use the group as their parent, instead of the original
|
|
||||||
// common parent, but, don't forget to put everything into a With block, like this:
|
|
||||||
//
|
|
||||||
// group.With(func() {
|
|
||||||
// object := newArbitratyObject(group, ...) // group is the parent of the object
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// When dealing with objects associated with a group, it's always necessary to wrap that into
|
|
||||||
// a With block:
|
|
||||||
//
|
|
||||||
// group.With(func() {
|
|
||||||
// for _, obj := range objectsWithCommonParent {
|
|
||||||
// // do something with obj
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// That's all!
|
|
||||||
type Group struct {
|
|
||||||
parent pixelgl.Doer
|
|
||||||
context pixelgl.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGroup creates a new group with the specified parent.
|
|
||||||
func NewGroup(parent pixelgl.Doer) *Group {
|
|
||||||
return &Group{
|
|
||||||
parent: parent,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// With enables the parent of a group and executes sub.
|
|
||||||
func (g *Group) With(sub func()) {
|
|
||||||
g.parent.Do(func(ctx pixelgl.Context) {
|
|
||||||
g.context = ctx
|
|
||||||
sub()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do just passes a cached context to sub.
|
|
||||||
func (g *Group) Do(sub func(pixelgl.Context)) {
|
|
||||||
sub(g.context)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shape is a general drawable shape constructed from vertices.
|
// Shape is a general drawable shape constructed from vertices.
|
||||||
//
|
//
|
||||||
// Vertices are specified in the vertex array of a shape. A shape can have a picture, a color
|
// Vertices are specified in the vertex array of a shape. A shape can have a picture, a color
|
||||||
|
@ -83,21 +17,21 @@ func (g *Group) Do(sub func(pixelgl.Context)) {
|
||||||
// Usually you use this type only indirectly throught other specific shapes (sprites, polygons,
|
// Usually you use this type only indirectly throught other specific shapes (sprites, polygons,
|
||||||
// ...) embedding it.
|
// ...) embedding it.
|
||||||
type Shape struct {
|
type Shape struct {
|
||||||
parent pixelgl.Doer
|
|
||||||
picture *Picture
|
picture *Picture
|
||||||
color color.Color
|
color color.Color
|
||||||
transform Transform
|
transform Transform
|
||||||
va *pixelgl.VertexArray
|
vertices []map[pixelgl.Attr]interface{}
|
||||||
|
vas map[Target]*pixelgl.VertexArray
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewShape creates a new shape with specified parent, picture, color, transform and vertex array.
|
// NewShape creates a new shape with specified parent, picture, color, transform and vertex array.
|
||||||
func NewShape(parent pixelgl.Doer, picture *Picture, c color.Color, transform Transform, va *pixelgl.VertexArray) *Shape {
|
func NewShape(picture *Picture, c color.Color, transform Transform, vertices []map[pixelgl.Attr]interface{}) *Shape {
|
||||||
return &Shape{
|
return &Shape{
|
||||||
parent: parent,
|
|
||||||
picture: picture,
|
picture: picture,
|
||||||
color: c,
|
color: c,
|
||||||
transform: transform,
|
transform: transform,
|
||||||
va: va,
|
vertices: vertices,
|
||||||
|
vas: make(map[Target]*pixelgl.VertexArray),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,30 +65,45 @@ func (s *Shape) Transform() Transform {
|
||||||
return s.transform
|
return s.transform
|
||||||
}
|
}
|
||||||
|
|
||||||
// VertexArray changes the underlying vertex array of a shape.
|
// Vertices returns the vertex attribute values of all vertices in a shape.
|
||||||
func (s *Shape) VertexArray() *pixelgl.VertexArray {
|
//
|
||||||
return s.va
|
// Do not change!
|
||||||
|
func (s *Shape) Vertices() []map[pixelgl.Attr]interface{} {
|
||||||
|
return s.vertices
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws a sprite transformed by the supplied transforms applied in the reverse order.
|
// Draw draws a sprite transformed by the supplied transforms applied in the reverse order.
|
||||||
func (s *Shape) Draw(t ...Transform) {
|
func (s *Shape) Draw(target Target, t ...Transform) {
|
||||||
mat := mgl32.Ident3()
|
mat := mgl32.Ident3()
|
||||||
for i := range t {
|
for i := range t {
|
||||||
mat = mat.Mul3(t[i].Mat())
|
mat = mat.Mul3(t[i].Mat())
|
||||||
}
|
}
|
||||||
mat = mat.Mul3(s.transform.Mat())
|
mat = mat.Mul3(s.transform.Mat())
|
||||||
|
|
||||||
s.parent.Do(func(ctx pixelgl.Context) {
|
c := NRGBAModel.Convert(s.color).(NRGBA)
|
||||||
c := NRGBAModel.Convert(s.color).(NRGBA)
|
|
||||||
ctx.Shader().SetUniformAttr(maskColorVec4, mgl32.Vec4{float32(c.R), float32(c.G), float32(c.B), float32(c.A)})
|
if s.vas[target] == nil {
|
||||||
ctx.Shader().SetUniformAttr(transformMat3, mat)
|
s.vas[target] = target.MakeVertexArray(s.vertices)
|
||||||
|
}
|
||||||
|
va := s.vas[target]
|
||||||
|
|
||||||
|
pixelgl.Do(func() {
|
||||||
|
target.Begin()
|
||||||
|
defer target.End()
|
||||||
|
|
||||||
|
target.Shader().SetUniformAttr(maskColorVec4, mgl32.Vec4{float32(c.R), float32(c.G), float32(c.B), float32(c.A)})
|
||||||
|
target.Shader().SetUniformAttr(transformMat3, mat)
|
||||||
|
|
||||||
if s.picture != nil {
|
if s.picture != nil {
|
||||||
s.picture.Texture().Do(func(pixelgl.Context) {
|
s.picture.Texture().Begin()
|
||||||
s.va.Draw()
|
va.Begin()
|
||||||
})
|
va.Draw()
|
||||||
|
va.End()
|
||||||
|
s.picture.Texture().End()
|
||||||
} else {
|
} else {
|
||||||
s.va.Draw()
|
va.Begin()
|
||||||
|
va.Draw()
|
||||||
|
va.End()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -173,7 +122,7 @@ type MultiShape struct {
|
||||||
// NewMultiShape creates a new multishape from several other shapes.
|
// NewMultiShape creates a new multishape from several other shapes.
|
||||||
//
|
//
|
||||||
// If two of the supplied shapes have different pictures, this function panics.
|
// If two of the supplied shapes have different pictures, this function panics.
|
||||||
func NewMultiShape(parent pixelgl.Doer, shapes ...*Shape) *MultiShape {
|
func NewMultiShape(shapes ...*Shape) *MultiShape {
|
||||||
var picture *Picture
|
var picture *Picture
|
||||||
for _, shape := range shapes {
|
for _, shape := range shapes {
|
||||||
if picture != nil && shape.Picture() != nil && shape.Picture().Texture().ID() != picture.Texture().ID() {
|
if picture != nil && shape.Picture() != nil && shape.Picture().Texture().ID() != picture.Texture().ID() {
|
||||||
|
@ -184,20 +133,9 @@ func NewMultiShape(parent pixelgl.Doer, shapes ...*Shape) *MultiShape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var va *pixelgl.VertexArray
|
|
||||||
|
|
||||||
var indices []int
|
|
||||||
offset := 0
|
|
||||||
for _, shape := range shapes {
|
|
||||||
for _, i := range shape.va.Indices() {
|
|
||||||
indices = append(indices, offset+i)
|
|
||||||
}
|
|
||||||
offset += shape.VertexArray().NumVertices()
|
|
||||||
}
|
|
||||||
|
|
||||||
var vertices []map[pixelgl.Attr]interface{}
|
var vertices []map[pixelgl.Attr]interface{}
|
||||||
for _, shape := range shapes {
|
for _, shape := range shapes {
|
||||||
shapeVertices := shape.VertexArray().Vertices()
|
shapeVertices := shape.Vertices()
|
||||||
|
|
||||||
for vertex := range shapeVertices {
|
for vertex := range shapeVertices {
|
||||||
if pos, ok := shapeVertices[vertex][positionVec2]; ok {
|
if pos, ok := shapeVertices[vertex][positionVec2]; ok {
|
||||||
|
@ -221,22 +159,7 @@ func NewMultiShape(parent pixelgl.Doer, shapes ...*Shape) *MultiShape {
|
||||||
vertices = append(vertices, shapeVertices...)
|
vertices = append(vertices, shapeVertices...)
|
||||||
}
|
}
|
||||||
|
|
||||||
parent.Do(func(ctx pixelgl.Context) {
|
return &MultiShape{NewShape(picture, color.White, Position(0), vertices)}
|
||||||
var err error
|
|
||||||
va, err = pixelgl.NewVertexArray(
|
|
||||||
pixelgl.ContextHolder{Context: ctx},
|
|
||||||
ctx.Shader().VertexFormat(),
|
|
||||||
len(vertices),
|
|
||||||
indices,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
panic(errors.Wrap(err, "failed to create multishape"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
va.SetVertices(vertices)
|
|
||||||
|
|
||||||
return &MultiShape{NewShape(parent, picture, color.White, Position(0), va)}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sprite is a picture that can be drawn on the screen. Optionally it can be color masked
|
// Sprite is a picture that can be drawn on the screen. Optionally it can be color masked
|
||||||
|
@ -252,25 +175,10 @@ type Sprite struct {
|
||||||
|
|
||||||
// NewSprite creates a new sprite with the supplied picture. The sprite's size is the size of
|
// NewSprite creates a new sprite with the supplied picture. The sprite's size is the size of
|
||||||
// the supplied picture. If you want to change the sprite's size, change it's transform.
|
// the supplied picture. If you want to change the sprite's size, change it's transform.
|
||||||
func NewSprite(parent pixelgl.Doer, picture *Picture) *Sprite {
|
func NewSprite(picture *Picture) *Sprite {
|
||||||
var va *pixelgl.VertexArray
|
w, h := picture.Bounds().Size.XY()
|
||||||
|
|
||||||
parent.Do(func(ctx pixelgl.Context) {
|
|
||||||
var err error
|
|
||||||
va, err = pixelgl.NewVertexArray(
|
|
||||||
pixelgl.ContextHolder{Context: ctx},
|
|
||||||
ctx.Shader().VertexFormat(),
|
|
||||||
4,
|
|
||||||
[]int{0, 1, 2, 0, 2, 3},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
panic(errors.Wrap(err, "failed to create sprite"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
vertices := make([]map[pixelgl.Attr]interface{}, 4)
|
vertices := make([]map[pixelgl.Attr]interface{}, 4)
|
||||||
|
|
||||||
w, h := picture.Bounds().Size.XY()
|
|
||||||
for i, p := range []Vec{V(0, 0), V(w, 0), V(w, h), V(0, h)} {
|
for i, p := range []Vec{V(0, 0), V(w, 0), V(w, h), V(0, h)} {
|
||||||
texCoord := V(
|
texCoord := V(
|
||||||
(picture.Bounds().X()+p.X())/float64(picture.Texture().Width()),
|
(picture.Bounds().X()+p.X())/float64(picture.Texture().Width()),
|
||||||
|
@ -284,9 +192,16 @@ func NewSprite(parent pixelgl.Doer, picture *Picture) *Sprite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
va.SetVertices(vertices)
|
vertices = []map[pixelgl.Attr]interface{}{
|
||||||
|
vertices[0],
|
||||||
|
vertices[1],
|
||||||
|
vertices[2],
|
||||||
|
vertices[0],
|
||||||
|
vertices[2],
|
||||||
|
vertices[3],
|
||||||
|
}
|
||||||
|
|
||||||
return &Sprite{NewShape(parent, picture, color.White, Position(0), va)}
|
return &Sprite{NewShape(picture, color.White, Position(0), vertices)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LineColor a line shape (with sharp ends) filled with a single color.
|
// LineColor a line shape (with sharp ends) filled with a single color.
|
||||||
|
@ -296,26 +211,9 @@ type LineColor struct {
|
||||||
width float64
|
width float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLineColor creates a new line shape between points A and B filled with a single color. Parent
|
// NewLineColor creates a new line shape between points A and B filled with a single color.
|
||||||
// is an object that this shape belongs to, such as a window, or a graphics effect.
|
func NewLineColor(c color.Color, a, b Vec, width float64) *LineColor {
|
||||||
func NewLineColor(parent pixelgl.Doer, c color.Color, a, b Vec, width float64) *LineColor {
|
|
||||||
var va *pixelgl.VertexArray
|
|
||||||
|
|
||||||
parent.Do(func(ctx pixelgl.Context) {
|
|
||||||
var err error
|
|
||||||
va, err = pixelgl.NewVertexArray(
|
|
||||||
pixelgl.ContextHolder{Context: ctx},
|
|
||||||
ctx.Shader().VertexFormat(),
|
|
||||||
4,
|
|
||||||
[]int{0, 1, 2, 1, 2, 3},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
panic(errors.Wrap(err, "failed to create line"))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
vertices := make([]map[pixelgl.Attr]interface{}, 4)
|
vertices := make([]map[pixelgl.Attr]interface{}, 4)
|
||||||
|
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
vertices[i] = map[pixelgl.Attr]interface{}{
|
vertices[i] = map[pixelgl.Attr]interface{}{
|
||||||
colorVec4: mgl32.Vec4{1, 1, 1, 1},
|
colorVec4: mgl32.Vec4{1, 1, 1, 1},
|
||||||
|
@ -323,9 +221,16 @@ func NewLineColor(parent pixelgl.Doer, c color.Color, a, b Vec, width float64) *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
va.SetVertices(vertices)
|
vertices = []map[pixelgl.Attr]interface{}{
|
||||||
|
vertices[0],
|
||||||
|
vertices[1],
|
||||||
|
vertices[2],
|
||||||
|
vertices[1],
|
||||||
|
vertices[2],
|
||||||
|
vertices[3],
|
||||||
|
}
|
||||||
|
|
||||||
lc := &LineColor{NewShape(parent, nil, c, Position(0), va), a, b, width}
|
lc := &LineColor{NewShape(nil, c, Position(0), vertices), a, b, width}
|
||||||
lc.setPoints()
|
lc.setPoints()
|
||||||
return lc
|
return lc
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package pixel
|
||||||
|
|
||||||
|
import "github.com/faiface/pixel/pixelgl"
|
||||||
|
|
||||||
|
// Target is an OpenGL graphics destination such as a window, a canvas, and so on. Something that
|
||||||
|
// you can draw on.
|
||||||
|
type Target interface {
|
||||||
|
pixelgl.BeginEnder
|
||||||
|
Shader() *pixelgl.Shader
|
||||||
|
|
||||||
|
// MakeVertexArray returns a new vertex array drawable on the Target.
|
||||||
|
MakeVertexArray(vertices []map[pixelgl.Attr]interface{}) *pixelgl.VertexArray
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drawer is anything that can be drawn. It's by no means a drawer inside your table.
|
||||||
|
//
|
||||||
|
// Drawer consists of a single methods: Draw. Draw takes a target and any number of transform
|
||||||
|
// arguments. It's up to a Drawer to make sure that it draws correctly onto the provided target.
|
||||||
|
type Drawer interface {
|
||||||
|
Draw(target Target, t ...Transform)
|
||||||
|
}
|
23
picture.go
23
picture.go
|
@ -24,16 +24,19 @@ func NewPicture(img image.Image, smooth bool) *Picture {
|
||||||
rgba := image.NewRGBA(image.Rect(0, 0, img.Bounds().Dx(), img.Bounds().Dy()))
|
rgba := image.NewRGBA(image.Rect(0, 0, img.Bounds().Dx(), img.Bounds().Dy()))
|
||||||
draw.Draw(rgba, rgba.Bounds(), img, img.Bounds().Min, draw.Src)
|
draw.Draw(rgba, rgba.Bounds(), img, img.Bounds().Min, draw.Src)
|
||||||
|
|
||||||
texture, err := pixelgl.NewTexture(
|
var texture *pixelgl.Texture
|
||||||
pixelgl.NoOpDoer,
|
pixelgl.Do(func() {
|
||||||
img.Bounds().Dx(),
|
var err error
|
||||||
img.Bounds().Dy(),
|
texture, err = pixelgl.NewTexture(
|
||||||
smooth,
|
img.Bounds().Dx(),
|
||||||
rgba.Pix,
|
img.Bounds().Dy(),
|
||||||
)
|
smooth,
|
||||||
if err != nil {
|
rgba.Pix,
|
||||||
panic(errors.Wrap(err, "failed to create picture"))
|
)
|
||||||
}
|
if err != nil {
|
||||||
|
panic(errors.Wrap(err, "failed to create picture"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return &Picture{
|
return &Picture{
|
||||||
texture: texture,
|
texture: texture,
|
||||||
|
|
146
window.go
146
window.go
|
@ -2,7 +2,6 @@ package pixel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
@ -58,10 +57,10 @@ type WindowConfig struct {
|
||||||
|
|
||||||
// Window is a window handler. Use this type to manipulate a window (input, drawing, ...).
|
// Window is a window handler. Use this type to manipulate a window (input, drawing, ...).
|
||||||
type Window struct {
|
type Window struct {
|
||||||
enabled bool
|
enabled bool
|
||||||
window *glfw.Window
|
window *glfw.Window
|
||||||
config WindowConfig
|
config WindowConfig
|
||||||
defaultShader *pixelgl.Shader
|
shader *pixelgl.Shader
|
||||||
|
|
||||||
// need to save these to correctly restore a fullscreen window
|
// need to save these to correctly restore a fullscreen window
|
||||||
restore struct {
|
restore struct {
|
||||||
|
@ -74,6 +73,8 @@ type Window struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var currentWindow *Window
|
||||||
|
|
||||||
// NewWindow creates a new window with it's properties specified in the provided config.
|
// NewWindow creates a new window with it's properties specified in the provided config.
|
||||||
//
|
//
|
||||||
// If window creation fails, an error is returned.
|
// If window creation fails, an error is returned.
|
||||||
|
@ -103,7 +104,11 @@ func NewWindow(config WindowConfig) (*Window, error) {
|
||||||
glfw.WindowHint(glfw.Maximized, bool2int[config.Maximized])
|
glfw.WindowHint(glfw.Maximized, bool2int[config.Maximized])
|
||||||
glfw.WindowHint(glfw.Samples, config.MSAASamples)
|
glfw.WindowHint(glfw.Samples, config.MSAASamples)
|
||||||
|
|
||||||
w.window, err = glfw.CreateWindow(int(config.Width), int(config.Height), config.Title, nil, nil)
|
var share *glfw.Window
|
||||||
|
if currentWindow != nil {
|
||||||
|
share = currentWindow.window
|
||||||
|
}
|
||||||
|
w.window, err = glfw.CreateWindow(int(config.Width), int(config.Height), config.Title, nil, share)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -114,13 +119,11 @@ func NewWindow(config WindowConfig) (*Window, error) {
|
||||||
return nil, errors.Wrap(err, "creating window failed")
|
return nil, errors.Wrap(err, "creating window failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
w.initInput()
|
pixelgl.Do(func() {
|
||||||
|
w.Begin()
|
||||||
|
defer w.End()
|
||||||
|
|
||||||
w.SetFullscreen(config.Fullscreen)
|
w.shader, err = pixelgl.NewShader(
|
||||||
|
|
||||||
w.Do(func(pixelgl.Context) {
|
|
||||||
w.defaultShader, err = pixelgl.NewShader(
|
|
||||||
pixelgl.NoOpDoer,
|
|
||||||
defaultVertexFormat,
|
defaultVertexFormat,
|
||||||
defaultUniformFormat,
|
defaultUniformFormat,
|
||||||
defaultVertexShader,
|
defaultVertexShader,
|
||||||
|
@ -128,14 +131,21 @@ func NewWindow(config WindowConfig) (*Window, error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
// default uniforms
|
// default uniforms
|
||||||
w.defaultShader.SetUniformAttr(maskColorVec4, mgl32.Vec4{1, 1, 1, 1})
|
w.shader.Begin()
|
||||||
w.defaultShader.SetUniformAttr(transformMat3, mgl32.Ident3())
|
w.shader.SetUniformAttr(maskColorVec4, mgl32.Vec4{1, 1, 1, 1})
|
||||||
|
w.shader.SetUniformAttr(transformMat3, mgl32.Ident3())
|
||||||
|
|
||||||
|
// this is tricky, w.shader.End() is not needed here, because it will
|
||||||
|
// actually be ended by a deferred w.End() call
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Destroy()
|
w.Destroy()
|
||||||
return nil, errors.Wrap(err, "creating window failed")
|
return nil, errors.Wrap(err, "creating window failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.initInput()
|
||||||
|
w.SetFullscreen(config.Fullscreen)
|
||||||
|
|
||||||
runtime.SetFinalizer(w, (*Window).Destroy)
|
runtime.SetFinalizer(w, (*Window).Destroy)
|
||||||
|
|
||||||
return w, nil
|
return w, nil
|
||||||
|
@ -150,37 +160,42 @@ func (w *Window) Destroy() {
|
||||||
|
|
||||||
// Clear clears the window with a color.
|
// Clear clears the window with a color.
|
||||||
func (w *Window) Clear(c color.Color) {
|
func (w *Window) Clear(c color.Color) {
|
||||||
w.Do(func(pixelgl.Context) {
|
pixelgl.DoNoBlock(func() {
|
||||||
pixelgl.DoNoBlock(func() {
|
w.Begin()
|
||||||
c := NRGBAModel.Convert(c).(NRGBA)
|
defer w.End()
|
||||||
gl.ClearColor(float32(c.R), float32(c.G), float32(c.B), float32(c.A))
|
|
||||||
gl.Clear(gl.COLOR_BUFFER_BIT)
|
c := NRGBAModel.Convert(c).(NRGBA)
|
||||||
})
|
gl.ClearColor(float32(c.R), float32(c.G), float32(c.B), float32(c.A))
|
||||||
|
gl.Clear(gl.COLOR_BUFFER_BIT)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update swaps buffers and polls events.
|
// Update swaps buffers and polls events.
|
||||||
func (w *Window) Update() {
|
func (w *Window) Update() {
|
||||||
w.Do(func(pixelgl.Context) {
|
pixelgl.Do(func() {
|
||||||
pixelgl.Do(func() {
|
w.Begin()
|
||||||
if w.config.VSync {
|
defer w.End()
|
||||||
glfw.SwapInterval(1)
|
|
||||||
}
|
|
||||||
w.window.SwapBuffers()
|
|
||||||
})
|
|
||||||
|
|
||||||
w.updateInput()
|
if w.config.VSync {
|
||||||
|
glfw.SwapInterval(1)
|
||||||
|
}
|
||||||
|
w.window.SwapBuffers()
|
||||||
|
})
|
||||||
|
|
||||||
pixelgl.Do(func() {
|
w.updateInput()
|
||||||
w, h := w.window.GetSize()
|
|
||||||
gl.Viewport(0, 0, int32(w), int32(h))
|
pixelgl.Do(func() {
|
||||||
})
|
w.Begin()
|
||||||
|
defer w.End()
|
||||||
|
|
||||||
|
w, h := w.window.GetSize()
|
||||||
|
gl.Viewport(0, 0, int32(w), int32(h))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultShader returns the default shader used by a window.
|
// Shader returns the default shader used by a window.
|
||||||
func (w *Window) DefaultShader() *pixelgl.Shader {
|
func (w *Window) Shader() *pixelgl.Shader {
|
||||||
return w.defaultShader
|
return w.shader
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClosed sets the closed flag of a window.
|
// SetClosed sets the closed flag of a window.
|
||||||
|
@ -327,33 +342,50 @@ func (w *Window) Restore() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentWindow struct {
|
// Begin makes the OpenGL context of a window current and binds it's shader.
|
||||||
sync.Mutex
|
//
|
||||||
handler *Window
|
// You usually do not need to use this method, however, you have to use it when you're
|
||||||
|
// directly using this window's context (such as drawing on it using OpenGL).
|
||||||
|
//
|
||||||
|
// Note, that this method must be called inside the main OpenGL thread (pixelgl.Do/DoNoBlock/DoErr/DoVal).
|
||||||
|
func (w *Window) Begin() {
|
||||||
|
if currentWindow != w {
|
||||||
|
w.window.MakeContextCurrent()
|
||||||
|
pixelgl.Init()
|
||||||
|
currentWindow = w
|
||||||
|
}
|
||||||
|
if w.shader != nil {
|
||||||
|
w.shader.Begin()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do makes the context of this window current, if it's not already, and executes sub.
|
// End unbinds the shader of a window.
|
||||||
func (w *Window) Do(sub func(pixelgl.Context)) {
|
func (w *Window) End() {
|
||||||
if !w.enabled {
|
if w.shader != nil {
|
||||||
currentWindow.Lock()
|
w.shader.End()
|
||||||
defer currentWindow.Unlock()
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if currentWindow.handler != w {
|
// MakeVertexArray implements Target.
|
||||||
pixelgl.Do(func() {
|
func (w *Window) MakeVertexArray(vertices []map[pixelgl.Attr]interface{}) *pixelgl.VertexArray {
|
||||||
w.window.MakeContextCurrent()
|
var va *pixelgl.VertexArray
|
||||||
pixelgl.Init()
|
|
||||||
})
|
pixelgl.Do(func() {
|
||||||
currentWindow.handler = w
|
w.Begin()
|
||||||
|
defer w.End()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
va, err = pixelgl.NewVertexArray(w.Shader(), len(vertices))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
w.enabled = true
|
va.Begin()
|
||||||
if w.defaultShader != nil {
|
va.SetVertices(vertices)
|
||||||
w.defaultShader.Do(sub)
|
va.End()
|
||||||
} else {
|
})
|
||||||
sub(pixelgl.Context{})
|
|
||||||
}
|
return va
|
||||||
w.enabled = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultVertexFormat = pixelgl.AttrFormat{
|
var defaultVertexFormat = pixelgl.AttrFormat{
|
||||||
|
|
Loading…
Reference in New Issue