Use dep to vendor things
This commit is contained in:
431
vendor/github.com/faiface/pixel/pixelgl/canvas.go
generated
vendored
Normal file
431
vendor/github.com/faiface/pixel/pixelgl/canvas.go
generated
vendored
Normal file
@@ -0,0 +1,431 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/faiface/glhf"
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Canvas is an off-screen rectangular BasicTarget and Picture at the same time, that you can draw
|
||||
// onto.
|
||||
//
|
||||
// It supports TrianglesPosition, TrianglesColor, TrianglesPicture and PictureColor.
|
||||
type Canvas struct {
|
||||
gf *GLFrame
|
||||
shader *glhf.Shader
|
||||
|
||||
cmp pixel.ComposeMethod
|
||||
mat mgl32.Mat3
|
||||
col mgl32.Vec4
|
||||
smooth bool
|
||||
|
||||
sprite *pixel.Sprite
|
||||
}
|
||||
|
||||
var _ pixel.ComposeTarget = (*Canvas)(nil)
|
||||
|
||||
// NewCanvas creates a new empty, fully transparent Canvas with given bounds.
|
||||
func NewCanvas(bounds pixel.Rect) *Canvas {
|
||||
c := &Canvas{
|
||||
gf: NewGLFrame(bounds),
|
||||
mat: mgl32.Ident3(),
|
||||
col: mgl32.Vec4{1, 1, 1, 1},
|
||||
}
|
||||
|
||||
c.SetBounds(bounds)
|
||||
|
||||
var shader *glhf.Shader
|
||||
mainthread.Call(func() {
|
||||
var err error
|
||||
shader, err = glhf.NewShader(
|
||||
canvasVertexFormat,
|
||||
canvasUniformFormat,
|
||||
canvasVertexShader,
|
||||
canvasFragmentShader,
|
||||
)
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "failed to create Canvas, there's a bug in the shader"))
|
||||
}
|
||||
})
|
||||
c.shader = shader
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// MakeTriangles creates a specialized copy of the supplied Triangles that draws onto this Canvas.
|
||||
//
|
||||
// TrianglesPosition, TrianglesColor and TrianglesPicture are supported.
|
||||
func (c *Canvas) MakeTriangles(t pixel.Triangles) pixel.TargetTriangles {
|
||||
return &canvasTriangles{
|
||||
GLTriangles: NewGLTriangles(c.shader, t),
|
||||
dst: c,
|
||||
}
|
||||
}
|
||||
|
||||
// MakePicture create a specialized copy of the supplied Picture that draws onto this Canvas.
|
||||
//
|
||||
// PictureColor is supported.
|
||||
func (c *Canvas) MakePicture(p pixel.Picture) pixel.TargetPicture {
|
||||
if cp, ok := p.(*canvasPicture); ok {
|
||||
return &canvasPicture{
|
||||
GLPicture: cp.GLPicture,
|
||||
dst: c,
|
||||
}
|
||||
}
|
||||
if gp, ok := p.(GLPicture); ok {
|
||||
return &canvasPicture{
|
||||
GLPicture: gp,
|
||||
dst: c,
|
||||
}
|
||||
}
|
||||
return &canvasPicture{
|
||||
GLPicture: NewGLPicture(p),
|
||||
dst: c,
|
||||
}
|
||||
}
|
||||
|
||||
// SetMatrix sets a Matrix that every point will be projected by.
|
||||
func (c *Canvas) SetMatrix(m pixel.Matrix) {
|
||||
// pixel.Matrix is 3x2 with an implicit 0, 0, 1 row after it. So
|
||||
// [0] [2] [4] [0] [3] [6]
|
||||
// [1] [3] [5] => [1] [4] [7]
|
||||
// 0 0 1 0 0 1
|
||||
// since all matrix ops are affine, the last row never changes, and we don't need to copy it
|
||||
for i, j := range [...]int{0, 1, 3, 4, 6, 7} {
|
||||
c.mat[j] = float32(m[i])
|
||||
}
|
||||
}
|
||||
|
||||
// SetColorMask sets a color that every color in triangles or a picture will be multiplied by.
|
||||
func (c *Canvas) SetColorMask(col color.Color) {
|
||||
rgba := pixel.Alpha(1)
|
||||
if col != nil {
|
||||
rgba = pixel.ToRGBA(col)
|
||||
}
|
||||
c.col = mgl32.Vec4{
|
||||
float32(rgba.R),
|
||||
float32(rgba.G),
|
||||
float32(rgba.B),
|
||||
float32(rgba.A),
|
||||
}
|
||||
}
|
||||
|
||||
// SetComposeMethod sets a Porter-Duff composition method to be used in the following draws onto
|
||||
// this Canvas.
|
||||
func (c *Canvas) SetComposeMethod(cmp pixel.ComposeMethod) {
|
||||
c.cmp = cmp
|
||||
}
|
||||
|
||||
// SetBounds resizes the Canvas to the new bounds. Old content will be preserved.
|
||||
func (c *Canvas) SetBounds(bounds pixel.Rect) {
|
||||
c.gf.SetBounds(bounds)
|
||||
if c.sprite == nil {
|
||||
c.sprite = pixel.NewSprite(nil, pixel.Rect{})
|
||||
}
|
||||
c.sprite.Set(c, c.Bounds())
|
||||
//c.sprite.SetMatrix(pixel.IM.Moved(c.Bounds().Center()))
|
||||
}
|
||||
|
||||
// Bounds returns the rectangular bounds of the Canvas.
|
||||
func (c *Canvas) Bounds() pixel.Rect {
|
||||
return c.gf.Bounds()
|
||||
}
|
||||
|
||||
// SetSmooth sets whether stretched Pictures drawn onto this Canvas should be drawn smooth or
|
||||
// pixely.
|
||||
func (c *Canvas) SetSmooth(smooth bool) {
|
||||
c.smooth = smooth
|
||||
}
|
||||
|
||||
// Smooth returns whether stretched Pictures drawn onto this Canvas are set to be drawn smooth or
|
||||
// pixely.
|
||||
func (c *Canvas) Smooth() bool {
|
||||
return c.smooth
|
||||
}
|
||||
|
||||
// must be manually called inside mainthread
|
||||
func (c *Canvas) setGlhfBounds() {
|
||||
_, _, bw, bh := intBounds(c.gf.Bounds())
|
||||
glhf.Bounds(0, 0, bw, bh)
|
||||
}
|
||||
|
||||
// must be manually called inside mainthread
|
||||
func setBlendFunc(cmp pixel.ComposeMethod) {
|
||||
switch cmp {
|
||||
case pixel.ComposeOver:
|
||||
glhf.BlendFunc(glhf.One, glhf.OneMinusSrcAlpha)
|
||||
case pixel.ComposeIn:
|
||||
glhf.BlendFunc(glhf.DstAlpha, glhf.Zero)
|
||||
case pixel.ComposeOut:
|
||||
glhf.BlendFunc(glhf.OneMinusDstAlpha, glhf.Zero)
|
||||
case pixel.ComposeAtop:
|
||||
glhf.BlendFunc(glhf.DstAlpha, glhf.OneMinusSrcAlpha)
|
||||
case pixel.ComposeRover:
|
||||
glhf.BlendFunc(glhf.OneMinusDstAlpha, glhf.One)
|
||||
case pixel.ComposeRin:
|
||||
glhf.BlendFunc(glhf.Zero, glhf.SrcAlpha)
|
||||
case pixel.ComposeRout:
|
||||
glhf.BlendFunc(glhf.Zero, glhf.OneMinusSrcAlpha)
|
||||
case pixel.ComposeRatop:
|
||||
glhf.BlendFunc(glhf.OneMinusDstAlpha, glhf.SrcAlpha)
|
||||
case pixel.ComposeXor:
|
||||
glhf.BlendFunc(glhf.OneMinusDstAlpha, glhf.OneMinusSrcAlpha)
|
||||
case pixel.ComposePlus:
|
||||
glhf.BlendFunc(glhf.One, glhf.One)
|
||||
case pixel.ComposeCopy:
|
||||
glhf.BlendFunc(glhf.One, glhf.Zero)
|
||||
default:
|
||||
panic(errors.New("Canvas: invalid compose method"))
|
||||
}
|
||||
}
|
||||
|
||||
// Clear fills the whole Canvas with a single color.
|
||||
func (c *Canvas) Clear(color color.Color) {
|
||||
c.gf.Dirty()
|
||||
|
||||
rgba := pixel.ToRGBA(color)
|
||||
|
||||
// color masking
|
||||
rgba = rgba.Mul(pixel.RGBA{
|
||||
R: float64(c.col[0]),
|
||||
G: float64(c.col[1]),
|
||||
B: float64(c.col[2]),
|
||||
A: float64(c.col[3]),
|
||||
})
|
||||
|
||||
mainthread.CallNonBlock(func() {
|
||||
c.setGlhfBounds()
|
||||
c.gf.Frame().Begin()
|
||||
glhf.Clear(
|
||||
float32(rgba.R),
|
||||
float32(rgba.G),
|
||||
float32(rgba.B),
|
||||
float32(rgba.A),
|
||||
)
|
||||
c.gf.Frame().End()
|
||||
})
|
||||
}
|
||||
|
||||
// Color returns the color of the pixel over the given position inside the Canvas.
|
||||
func (c *Canvas) Color(at pixel.Vec) pixel.RGBA {
|
||||
return c.gf.Color(at)
|
||||
}
|
||||
|
||||
// Texture returns the underlying OpenGL Texture of this Canvas.
|
||||
//
|
||||
// Implements GLPicture interface.
|
||||
func (c *Canvas) Texture() *glhf.Texture {
|
||||
return c.gf.Texture()
|
||||
}
|
||||
|
||||
// Frame returns the underlying OpenGL Frame of this Canvas.
|
||||
func (c *Canvas) Frame() *glhf.Frame {
|
||||
return c.gf.frame
|
||||
}
|
||||
|
||||
// SetPixels replaces the content of the Canvas with the provided pixels. The provided slice must be
|
||||
// an alpha-premultiplied RGBA sequence of correct length (4 * width * height).
|
||||
func (c *Canvas) SetPixels(pixels []uint8) {
|
||||
c.gf.Dirty()
|
||||
|
||||
mainthread.Call(func() {
|
||||
tex := c.Texture()
|
||||
tex.Begin()
|
||||
tex.SetPixels(0, 0, tex.Width(), tex.Height(), pixels)
|
||||
tex.End()
|
||||
})
|
||||
}
|
||||
|
||||
// Pixels returns an alpha-premultiplied RGBA sequence of the content of the Canvas.
|
||||
func (c *Canvas) Pixels() []uint8 {
|
||||
var pixels []uint8
|
||||
|
||||
mainthread.Call(func() {
|
||||
tex := c.Texture()
|
||||
tex.Begin()
|
||||
pixels = tex.Pixels(0, 0, tex.Width(), tex.Height())
|
||||
tex.End()
|
||||
})
|
||||
|
||||
return pixels
|
||||
}
|
||||
|
||||
// Draw draws the content of the Canvas onto another Target, transformed by the given Matrix, just
|
||||
// like if it was a Sprite containing the whole Canvas.
|
||||
func (c *Canvas) Draw(t pixel.Target, matrix pixel.Matrix) {
|
||||
c.sprite.Draw(t, matrix)
|
||||
}
|
||||
|
||||
// DrawColorMask draws the content of the Canvas onto another Target, transformed by the given
|
||||
// Matrix and multiplied by the given mask, just like if it was a Sprite containing the whole Canvas.
|
||||
//
|
||||
// If the color mask is nil, a fully opaque white mask will be used causing no effect.
|
||||
func (c *Canvas) DrawColorMask(t pixel.Target, matrix pixel.Matrix, mask color.Color) {
|
||||
c.sprite.DrawColorMask(t, matrix, mask)
|
||||
}
|
||||
|
||||
type canvasTriangles struct {
|
||||
*GLTriangles
|
||||
dst *Canvas
|
||||
}
|
||||
|
||||
func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) {
|
||||
ct.dst.gf.Dirty()
|
||||
|
||||
// save the current state vars to avoid race condition
|
||||
cmp := ct.dst.cmp
|
||||
mat := ct.dst.mat
|
||||
col := ct.dst.col
|
||||
smt := ct.dst.smooth
|
||||
|
||||
mainthread.CallNonBlock(func() {
|
||||
ct.dst.setGlhfBounds()
|
||||
setBlendFunc(cmp)
|
||||
|
||||
frame := ct.dst.gf.Frame()
|
||||
shader := ct.dst.shader
|
||||
|
||||
frame.Begin()
|
||||
shader.Begin()
|
||||
|
||||
dstBounds := ct.dst.Bounds()
|
||||
shader.SetUniformAttr(canvasBounds, mgl32.Vec4{
|
||||
float32(dstBounds.Min.X),
|
||||
float32(dstBounds.Min.Y),
|
||||
float32(dstBounds.W()),
|
||||
float32(dstBounds.H()),
|
||||
})
|
||||
shader.SetUniformAttr(canvasTransform, mat)
|
||||
shader.SetUniformAttr(canvasColorMask, col)
|
||||
|
||||
if tex == nil {
|
||||
ct.vs.Begin()
|
||||
ct.vs.Draw()
|
||||
ct.vs.End()
|
||||
} else {
|
||||
tex.Begin()
|
||||
|
||||
bx, by, bw, bh := intBounds(bounds)
|
||||
shader.SetUniformAttr(canvasTexBounds, mgl32.Vec4{
|
||||
float32(bx),
|
||||
float32(by),
|
||||
float32(bw),
|
||||
float32(bh),
|
||||
})
|
||||
|
||||
if tex.Smooth() != smt {
|
||||
tex.SetSmooth(smt)
|
||||
}
|
||||
|
||||
ct.vs.Begin()
|
||||
ct.vs.Draw()
|
||||
ct.vs.End()
|
||||
|
||||
tex.End()
|
||||
}
|
||||
|
||||
shader.End()
|
||||
frame.End()
|
||||
})
|
||||
}
|
||||
|
||||
func (ct *canvasTriangles) Draw() {
|
||||
ct.draw(nil, pixel.Rect{})
|
||||
}
|
||||
|
||||
type canvasPicture struct {
|
||||
GLPicture
|
||||
dst *Canvas
|
||||
}
|
||||
|
||||
func (cp *canvasPicture) Draw(t pixel.TargetTriangles) {
|
||||
ct := t.(*canvasTriangles)
|
||||
if cp.dst != ct.dst {
|
||||
panic(fmt.Errorf("(%T).Draw: TargetTriangles generated by different Canvas", cp))
|
||||
}
|
||||
ct.draw(cp.GLPicture.Texture(), cp.GLPicture.Bounds())
|
||||
}
|
||||
|
||||
const (
|
||||
canvasPosition int = iota
|
||||
canvasColor
|
||||
canvasTexCoords
|
||||
canvasIntensity
|
||||
)
|
||||
|
||||
var canvasVertexFormat = glhf.AttrFormat{
|
||||
canvasPosition: {Name: "position", Type: glhf.Vec2},
|
||||
canvasColor: {Name: "color", Type: glhf.Vec4},
|
||||
canvasTexCoords: {Name: "texCoords", Type: glhf.Vec2},
|
||||
canvasIntensity: {Name: "intensity", Type: glhf.Float},
|
||||
}
|
||||
|
||||
const (
|
||||
canvasTransform int = iota
|
||||
canvasColorMask
|
||||
canvasBounds
|
||||
canvasTexBounds
|
||||
)
|
||||
|
||||
var canvasUniformFormat = glhf.AttrFormat{
|
||||
canvasTransform: {Name: "transform", Type: glhf.Mat3},
|
||||
canvasColorMask: {Name: "colorMask", Type: glhf.Vec4},
|
||||
canvasBounds: {Name: "bounds", Type: glhf.Vec4},
|
||||
canvasTexBounds: {Name: "texBounds", Type: glhf.Vec4},
|
||||
}
|
||||
|
||||
var canvasVertexShader = `
|
||||
#version 330 core
|
||||
|
||||
in vec2 position;
|
||||
in vec4 color;
|
||||
in vec2 texCoords;
|
||||
in float intensity;
|
||||
|
||||
out vec4 Color;
|
||||
out vec2 TexCoords;
|
||||
out float Intensity;
|
||||
|
||||
uniform mat3 transform;
|
||||
uniform vec4 bounds;
|
||||
|
||||
void main() {
|
||||
vec2 transPos = (transform * vec3(position, 1.0)).xy;
|
||||
vec2 normPos = (transPos - bounds.xy) / bounds.zw * 2 - vec2(1, 1);
|
||||
gl_Position = vec4(normPos, 0.0, 1.0);
|
||||
Color = color;
|
||||
TexCoords = texCoords;
|
||||
Intensity = intensity;
|
||||
}
|
||||
`
|
||||
|
||||
var canvasFragmentShader = `
|
||||
#version 330 core
|
||||
|
||||
in vec4 Color;
|
||||
in vec2 TexCoords;
|
||||
in float Intensity;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec4 colorMask;
|
||||
uniform vec4 texBounds;
|
||||
uniform sampler2D tex;
|
||||
|
||||
void main() {
|
||||
if (Intensity == 0) {
|
||||
color = colorMask * Color;
|
||||
} else {
|
||||
color = vec4(0, 0, 0, 0);
|
||||
color += (1 - Intensity) * Color;
|
||||
vec2 t = (TexCoords - texBounds.xy) / texBounds.zw;
|
||||
color += Intensity * Color * texture(tex, t);
|
||||
color *= colorMask;
|
||||
}
|
||||
}
|
||||
`
|
5
vendor/github.com/faiface/pixel/pixelgl/doc.go
generated
vendored
Normal file
5
vendor/github.com/faiface/pixel/pixelgl/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// Package pixelgl implements efficient OpenGL targets and utilities for the Pixel game development
|
||||
// library, specifically Window and Canvas.
|
||||
//
|
||||
// It also contains a few additional utilities to help extend Pixel with OpenGL graphical effects.
|
||||
package pixelgl
|
105
vendor/github.com/faiface/pixel/pixelgl/glframe.go
generated
vendored
Normal file
105
vendor/github.com/faiface/pixel/pixelgl/glframe.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"github.com/faiface/glhf"
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/faiface/pixel"
|
||||
)
|
||||
|
||||
// GLFrame is a type that helps implementing OpenGL Targets. It implements most common methods to
|
||||
// avoid code redundancy. It contains an glhf.Frame that you can draw on.
|
||||
type GLFrame struct {
|
||||
frame *glhf.Frame
|
||||
bounds pixel.Rect
|
||||
pixels []uint8
|
||||
dirty bool
|
||||
}
|
||||
|
||||
// NewGLFrame creates a new GLFrame with the given bounds.
|
||||
func NewGLFrame(bounds pixel.Rect) *GLFrame {
|
||||
gf := new(GLFrame)
|
||||
gf.SetBounds(bounds)
|
||||
return gf
|
||||
}
|
||||
|
||||
// SetBounds resizes the GLFrame to the new bounds.
|
||||
func (gf *GLFrame) SetBounds(bounds pixel.Rect) {
|
||||
if bounds == gf.Bounds() {
|
||||
return
|
||||
}
|
||||
|
||||
mainthread.Call(func() {
|
||||
oldF := gf.frame
|
||||
|
||||
_, _, w, h := intBounds(bounds)
|
||||
if w <= 0 {
|
||||
w = 1
|
||||
}
|
||||
if h <= 0 {
|
||||
h = 1
|
||||
}
|
||||
gf.frame = glhf.NewFrame(w, h, false)
|
||||
|
||||
// preserve old content
|
||||
if oldF != nil {
|
||||
ox, oy, ow, oh := intBounds(bounds)
|
||||
oldF.Blit(
|
||||
gf.frame,
|
||||
ox, oy, ox+ow, oy+oh,
|
||||
ox, oy, ox+ow, oy+oh,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
gf.bounds = bounds
|
||||
gf.pixels = nil
|
||||
gf.dirty = true
|
||||
}
|
||||
|
||||
// Bounds returns the current GLFrame's bounds.
|
||||
func (gf *GLFrame) Bounds() pixel.Rect {
|
||||
return gf.bounds
|
||||
}
|
||||
|
||||
// Color returns the color of the pixel under the specified position.
|
||||
func (gf *GLFrame) Color(at pixel.Vec) pixel.RGBA {
|
||||
if gf.dirty {
|
||||
mainthread.Call(func() {
|
||||
tex := gf.frame.Texture()
|
||||
tex.Begin()
|
||||
gf.pixels = tex.Pixels(0, 0, tex.Width(), tex.Height())
|
||||
tex.End()
|
||||
})
|
||||
gf.dirty = false
|
||||
}
|
||||
if !gf.bounds.Contains(at) {
|
||||
return pixel.Alpha(0)
|
||||
}
|
||||
bx, by, bw, _ := intBounds(gf.bounds)
|
||||
x, y := int(at.X)-bx, int(at.Y)-by
|
||||
off := y*bw + x
|
||||
return pixel.RGBA{
|
||||
R: float64(gf.pixels[off*4+0]) / 255,
|
||||
G: float64(gf.pixels[off*4+1]) / 255,
|
||||
B: float64(gf.pixels[off*4+2]) / 255,
|
||||
A: float64(gf.pixels[off*4+3]) / 255,
|
||||
}
|
||||
}
|
||||
|
||||
// Frame returns the GLFrame's Frame that you can draw on.
|
||||
func (gf *GLFrame) Frame() *glhf.Frame {
|
||||
return gf.frame
|
||||
}
|
||||
|
||||
// Texture returns the underlying Texture of the GLFrame's Frame.
|
||||
//
|
||||
// Implements GLPicture interface.
|
||||
func (gf *GLFrame) Texture() *glhf.Texture {
|
||||
return gf.frame.Texture()
|
||||
}
|
||||
|
||||
// Dirty marks the GLFrame as changed. Always call this method when you draw onto the GLFrame's
|
||||
// Frame.
|
||||
func (gf *GLFrame) Dirty() {
|
||||
gf.dirty = true
|
||||
}
|
98
vendor/github.com/faiface/pixel/pixelgl/glpicture.go
generated
vendored
Normal file
98
vendor/github.com/faiface/pixel/pixelgl/glpicture.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/faiface/glhf"
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/faiface/pixel"
|
||||
)
|
||||
|
||||
// GLPicture is a pixel.PictureColor with a Texture. All OpenGL Targets should implement and accept
|
||||
// this interface, because it enables seamless drawing of one to another.
|
||||
//
|
||||
// Implementing this interface on an OpenGL Target enables other OpenGL Targets to efficiently draw
|
||||
// that Target onto them.
|
||||
type GLPicture interface {
|
||||
pixel.PictureColor
|
||||
Texture() *glhf.Texture
|
||||
}
|
||||
|
||||
// NewGLPicture creates a new GLPicture with it's own static OpenGL texture. This function always
|
||||
// allocates a new texture that cannot (shouldn't) be further modified.
|
||||
func NewGLPicture(p pixel.Picture) GLPicture {
|
||||
bounds := p.Bounds()
|
||||
bx, by, bw, bh := intBounds(bounds)
|
||||
|
||||
pixels := make([]uint8, 4*bw*bh)
|
||||
|
||||
if pd, ok := p.(*pixel.PictureData); ok {
|
||||
// PictureData short path
|
||||
for y := 0; y < bh; y++ {
|
||||
for x := 0; x < bw; x++ {
|
||||
rgba := pd.Pix[y*pd.Stride+x]
|
||||
off := (y*bw + x) * 4
|
||||
pixels[off+0] = rgba.R
|
||||
pixels[off+1] = rgba.G
|
||||
pixels[off+2] = rgba.B
|
||||
pixels[off+3] = rgba.A
|
||||
}
|
||||
}
|
||||
} else if p, ok := p.(pixel.PictureColor); ok {
|
||||
for y := 0; y < bh; y++ {
|
||||
for x := 0; x < bw; x++ {
|
||||
at := pixel.V(
|
||||
math.Max(float64(bx+x), bounds.Min.X),
|
||||
math.Max(float64(by+y), bounds.Min.Y),
|
||||
)
|
||||
color := p.Color(at)
|
||||
off := (y*bw + x) * 4
|
||||
pixels[off+0] = uint8(color.R * 255)
|
||||
pixels[off+1] = uint8(color.G * 255)
|
||||
pixels[off+2] = uint8(color.B * 255)
|
||||
pixels[off+3] = uint8(color.A * 255)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var tex *glhf.Texture
|
||||
mainthread.Call(func() {
|
||||
tex = glhf.NewTexture(bw, bh, false, pixels)
|
||||
})
|
||||
|
||||
gp := &glPicture{
|
||||
bounds: bounds,
|
||||
tex: tex,
|
||||
pixels: pixels,
|
||||
}
|
||||
return gp
|
||||
}
|
||||
|
||||
type glPicture struct {
|
||||
bounds pixel.Rect
|
||||
tex *glhf.Texture
|
||||
pixels []uint8
|
||||
}
|
||||
|
||||
func (gp *glPicture) Bounds() pixel.Rect {
|
||||
return gp.bounds
|
||||
}
|
||||
|
||||
func (gp *glPicture) Texture() *glhf.Texture {
|
||||
return gp.tex
|
||||
}
|
||||
|
||||
func (gp *glPicture) Color(at pixel.Vec) pixel.RGBA {
|
||||
if !gp.bounds.Contains(at) {
|
||||
return pixel.Alpha(0)
|
||||
}
|
||||
bx, by, bw, _ := intBounds(gp.bounds)
|
||||
x, y := int(at.X)-bx, int(at.Y)-by
|
||||
off := y*bw + x
|
||||
return pixel.RGBA{
|
||||
R: float64(gp.pixels[off*4+0]) / 255,
|
||||
G: float64(gp.pixels[off*4+1]) / 255,
|
||||
B: float64(gp.pixels[off*4+2]) / 255,
|
||||
A: float64(gp.pixels[off*4+3]) / 255,
|
||||
}
|
||||
}
|
215
vendor/github.com/faiface/pixel/pixelgl/gltriangles.go
generated
vendored
Normal file
215
vendor/github.com/faiface/pixel/pixelgl/gltriangles.go
generated
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/faiface/glhf"
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/faiface/pixel"
|
||||
)
|
||||
|
||||
// GLTriangles are OpenGL triangles implemented using glhf.VertexSlice.
|
||||
//
|
||||
// Triangles returned from this function support TrianglesPosition, TrianglesColor and
|
||||
// TrianglesPicture. If you need to support more, you can "override" SetLen and Update methods.
|
||||
type GLTriangles struct {
|
||||
vs *glhf.VertexSlice
|
||||
data []float32
|
||||
shader *glhf.Shader
|
||||
}
|
||||
|
||||
var (
|
||||
_ pixel.TrianglesPosition = (*GLTriangles)(nil)
|
||||
_ pixel.TrianglesColor = (*GLTriangles)(nil)
|
||||
_ pixel.TrianglesPicture = (*GLTriangles)(nil)
|
||||
)
|
||||
|
||||
// NewGLTriangles returns GLTriangles initialized with the data from the supplied Triangles.
|
||||
//
|
||||
// Only draw the Triangles using the provided Shader.
|
||||
func NewGLTriangles(shader *glhf.Shader, t pixel.Triangles) *GLTriangles {
|
||||
var gt *GLTriangles
|
||||
mainthread.Call(func() {
|
||||
gt = &GLTriangles{
|
||||
vs: glhf.MakeVertexSlice(shader, 0, t.Len()),
|
||||
shader: shader,
|
||||
}
|
||||
})
|
||||
gt.SetLen(t.Len())
|
||||
gt.Update(t)
|
||||
return gt
|
||||
}
|
||||
|
||||
// VertexSlice returns the VertexSlice of this GLTriangles.
|
||||
//
|
||||
// You can use it to draw them.
|
||||
func (gt *GLTriangles) VertexSlice() *glhf.VertexSlice {
|
||||
return gt.vs
|
||||
}
|
||||
|
||||
// Shader returns the GLTriangles's associated shader.
|
||||
func (gt *GLTriangles) Shader() *glhf.Shader {
|
||||
return gt.shader
|
||||
}
|
||||
|
||||
// Len returns the number of vertices.
|
||||
func (gt *GLTriangles) Len() int {
|
||||
return len(gt.data) / gt.vs.Stride()
|
||||
}
|
||||
|
||||
// SetLen efficiently resizes GLTriangles to len.
|
||||
//
|
||||
// Time complexity is amortized O(1).
|
||||
func (gt *GLTriangles) SetLen(length int) {
|
||||
switch {
|
||||
case length > gt.Len():
|
||||
needAppend := length - gt.Len()
|
||||
for i := 0; i < needAppend; i++ {
|
||||
gt.data = append(gt.data,
|
||||
0, 0,
|
||||
1, 1, 1, 1,
|
||||
0, 0,
|
||||
0,
|
||||
)
|
||||
}
|
||||
case length < gt.Len():
|
||||
gt.data = gt.data[:length*gt.vs.Stride()]
|
||||
default:
|
||||
return
|
||||
}
|
||||
mainthread.CallNonBlock(func() {
|
||||
gt.vs.Begin()
|
||||
gt.vs.SetLen(length)
|
||||
gt.vs.End()
|
||||
})
|
||||
}
|
||||
|
||||
// Slice returns a sub-Triangles of this GLTriangles in range [i, j).
|
||||
func (gt *GLTriangles) Slice(i, j int) pixel.Triangles {
|
||||
return &GLTriangles{
|
||||
vs: gt.vs.Slice(i, j),
|
||||
data: gt.data[i*gt.vs.Stride() : j*gt.vs.Stride()],
|
||||
shader: gt.shader,
|
||||
}
|
||||
}
|
||||
|
||||
func (gt *GLTriangles) updateData(t pixel.Triangles) {
|
||||
// glTriangles short path
|
||||
if t, ok := t.(*GLTriangles); ok {
|
||||
copy(gt.data, t.data)
|
||||
return
|
||||
}
|
||||
|
||||
// TrianglesData short path
|
||||
stride := gt.vs.Stride()
|
||||
length := gt.Len()
|
||||
if t, ok := t.(*pixel.TrianglesData); ok {
|
||||
for i := 0; i < length; i++ {
|
||||
var (
|
||||
px, py = (*t)[i].Position.XY()
|
||||
col = (*t)[i].Color
|
||||
tx, ty = (*t)[i].Picture.XY()
|
||||
in = (*t)[i].Intensity
|
||||
)
|
||||
d := gt.data[i*stride : i*stride+9]
|
||||
d[0] = float32(px)
|
||||
d[1] = float32(py)
|
||||
d[2] = float32(col.R)
|
||||
d[3] = float32(col.G)
|
||||
d[4] = float32(col.B)
|
||||
d[5] = float32(col.A)
|
||||
d[6] = float32(tx)
|
||||
d[7] = float32(ty)
|
||||
d[8] = float32(in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if t, ok := t.(pixel.TrianglesPosition); ok {
|
||||
for i := 0; i < length; i++ {
|
||||
px, py := t.Position(i).XY()
|
||||
gt.data[i*stride+0] = float32(px)
|
||||
gt.data[i*stride+1] = float32(py)
|
||||
}
|
||||
}
|
||||
if t, ok := t.(pixel.TrianglesColor); ok {
|
||||
for i := 0; i < length; i++ {
|
||||
col := t.Color(i)
|
||||
gt.data[i*stride+2] = float32(col.R)
|
||||
gt.data[i*stride+3] = float32(col.G)
|
||||
gt.data[i*stride+4] = float32(col.B)
|
||||
gt.data[i*stride+5] = float32(col.A)
|
||||
}
|
||||
}
|
||||
if t, ok := t.(pixel.TrianglesPicture); ok {
|
||||
for i := 0; i < length; i++ {
|
||||
pic, intensity := t.Picture(i)
|
||||
gt.data[i*stride+6] = float32(pic.X)
|
||||
gt.data[i*stride+7] = float32(pic.Y)
|
||||
gt.data[i*stride+8] = float32(intensity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update copies vertex properties from the supplied Triangles into this GLTriangles.
|
||||
//
|
||||
// The two Triangles (gt and t) must be of the same len.
|
||||
func (gt *GLTriangles) Update(t pixel.Triangles) {
|
||||
if gt.Len() != t.Len() {
|
||||
panic(fmt.Errorf("(%T).Update: invalid triangles len", gt))
|
||||
}
|
||||
gt.updateData(t)
|
||||
|
||||
// this code is supposed to copy the vertex data and CallNonBlock the update if
|
||||
// the data is small enough, otherwise it'll block and not copy the data
|
||||
if len(gt.data) < 256 { // arbitrary heurestic constant
|
||||
data := append([]float32{}, gt.data...)
|
||||
mainthread.CallNonBlock(func() {
|
||||
gt.vs.Begin()
|
||||
gt.vs.SetVertexData(data)
|
||||
gt.vs.End()
|
||||
})
|
||||
} else {
|
||||
mainthread.Call(func() {
|
||||
gt.vs.Begin()
|
||||
gt.vs.SetVertexData(gt.data)
|
||||
gt.vs.End()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Copy returns an independent copy of this GLTriangles.
|
||||
//
|
||||
// The returned Triangles are *GLTriangles as the underlying type.
|
||||
func (gt *GLTriangles) Copy() pixel.Triangles {
|
||||
return NewGLTriangles(gt.shader, gt)
|
||||
}
|
||||
|
||||
// Position returns the Position property of the i-th vertex.
|
||||
func (gt *GLTriangles) Position(i int) pixel.Vec {
|
||||
px := gt.data[i*gt.vs.Stride()+0]
|
||||
py := gt.data[i*gt.vs.Stride()+1]
|
||||
return pixel.V(float64(px), float64(py))
|
||||
}
|
||||
|
||||
// Color returns the Color property of the i-th vertex.
|
||||
func (gt *GLTriangles) Color(i int) pixel.RGBA {
|
||||
r := gt.data[i*gt.vs.Stride()+2]
|
||||
g := gt.data[i*gt.vs.Stride()+3]
|
||||
b := gt.data[i*gt.vs.Stride()+4]
|
||||
a := gt.data[i*gt.vs.Stride()+5]
|
||||
return pixel.RGBA{
|
||||
R: float64(r),
|
||||
G: float64(g),
|
||||
B: float64(b),
|
||||
A: float64(a),
|
||||
}
|
||||
}
|
||||
|
||||
// Picture returns the Picture property of the i-th vertex.
|
||||
func (gt *GLTriangles) Picture(i int) (pic pixel.Vec, intensity float64) {
|
||||
tx := gt.data[i*gt.vs.Stride()+6]
|
||||
ty := gt.data[i*gt.vs.Stride()+7]
|
||||
intensity = float64(gt.data[i*gt.vs.Stride()+8])
|
||||
return pixel.V(float64(tx), float64(ty)), intensity
|
||||
}
|
388
vendor/github.com/faiface/pixel/pixelgl/input.go
generated
vendored
Normal file
388
vendor/github.com/faiface/pixel/pixelgl/input.go
generated
vendored
Normal file
@@ -0,0 +1,388 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/go-gl/glfw/v3.2/glfw"
|
||||
)
|
||||
|
||||
// Pressed returns whether the Button is currently pressed down.
|
||||
func (w *Window) Pressed(button Button) bool {
|
||||
return w.currInp.buttons[button]
|
||||
}
|
||||
|
||||
// JustPressed returns whether the Button has just been pressed down.
|
||||
func (w *Window) JustPressed(button Button) bool {
|
||||
return w.currInp.buttons[button] && !w.prevInp.buttons[button]
|
||||
}
|
||||
|
||||
// JustReleased returns whether the Button has just been released up.
|
||||
func (w *Window) JustReleased(button Button) bool {
|
||||
return !w.currInp.buttons[button] && w.prevInp.buttons[button]
|
||||
}
|
||||
|
||||
// Repeated returns whether a repeat event has been triggered on button.
|
||||
//
|
||||
// Repeat event occurs repeatedly when a button is held down for some time.
|
||||
func (w *Window) Repeated(button Button) bool {
|
||||
return w.currInp.repeat[button]
|
||||
}
|
||||
|
||||
// MousePosition returns the current mouse position in the Window's Bounds.
|
||||
func (w *Window) MousePosition() pixel.Vec {
|
||||
return w.currInp.mouse
|
||||
}
|
||||
|
||||
// MouseScroll returns the mouse scroll amount (in both axes) since the last call to Window.Update.
|
||||
func (w *Window) MouseScroll() pixel.Vec {
|
||||
return w.currInp.scroll
|
||||
}
|
||||
|
||||
// Typed returns the text typed on the keyboard since the last call to Window.Update.
|
||||
func (w *Window) Typed() string {
|
||||
return w.currInp.typed
|
||||
}
|
||||
|
||||
// Button is a keyboard or mouse button. Why distinguish?
|
||||
type Button int
|
||||
|
||||
// List of all mouse buttons.
|
||||
const (
|
||||
MouseButton1 = Button(glfw.MouseButton1)
|
||||
MouseButton2 = Button(glfw.MouseButton2)
|
||||
MouseButton3 = Button(glfw.MouseButton3)
|
||||
MouseButton4 = Button(glfw.MouseButton4)
|
||||
MouseButton5 = Button(glfw.MouseButton5)
|
||||
MouseButton6 = Button(glfw.MouseButton6)
|
||||
MouseButton7 = Button(glfw.MouseButton7)
|
||||
MouseButton8 = Button(glfw.MouseButton8)
|
||||
MouseButtonLast = Button(glfw.MouseButtonLast)
|
||||
MouseButtonLeft = Button(glfw.MouseButtonLeft)
|
||||
MouseButtonRight = Button(glfw.MouseButtonRight)
|
||||
MouseButtonMiddle = Button(glfw.MouseButtonMiddle)
|
||||
)
|
||||
|
||||
// List of all keyboard buttons.
|
||||
const (
|
||||
KeyUnknown = Button(glfw.KeyUnknown)
|
||||
KeySpace = Button(glfw.KeySpace)
|
||||
KeyApostrophe = Button(glfw.KeyApostrophe)
|
||||
KeyComma = Button(glfw.KeyComma)
|
||||
KeyMinus = Button(glfw.KeyMinus)
|
||||
KeyPeriod = Button(glfw.KeyPeriod)
|
||||
KeySlash = Button(glfw.KeySlash)
|
||||
Key0 = Button(glfw.Key0)
|
||||
Key1 = Button(glfw.Key1)
|
||||
Key2 = Button(glfw.Key2)
|
||||
Key3 = Button(glfw.Key3)
|
||||
Key4 = Button(glfw.Key4)
|
||||
Key5 = Button(glfw.Key5)
|
||||
Key6 = Button(glfw.Key6)
|
||||
Key7 = Button(glfw.Key7)
|
||||
Key8 = Button(glfw.Key8)
|
||||
Key9 = Button(glfw.Key9)
|
||||
KeySemicolon = Button(glfw.KeySemicolon)
|
||||
KeyEqual = Button(glfw.KeyEqual)
|
||||
KeyA = Button(glfw.KeyA)
|
||||
KeyB = Button(glfw.KeyB)
|
||||
KeyC = Button(glfw.KeyC)
|
||||
KeyD = Button(glfw.KeyD)
|
||||
KeyE = Button(glfw.KeyE)
|
||||
KeyF = Button(glfw.KeyF)
|
||||
KeyG = Button(glfw.KeyG)
|
||||
KeyH = Button(glfw.KeyH)
|
||||
KeyI = Button(glfw.KeyI)
|
||||
KeyJ = Button(glfw.KeyJ)
|
||||
KeyK = Button(glfw.KeyK)
|
||||
KeyL = Button(glfw.KeyL)
|
||||
KeyM = Button(glfw.KeyM)
|
||||
KeyN = Button(glfw.KeyN)
|
||||
KeyO = Button(glfw.KeyO)
|
||||
KeyP = Button(glfw.KeyP)
|
||||
KeyQ = Button(glfw.KeyQ)
|
||||
KeyR = Button(glfw.KeyR)
|
||||
KeyS = Button(glfw.KeyS)
|
||||
KeyT = Button(glfw.KeyT)
|
||||
KeyU = Button(glfw.KeyU)
|
||||
KeyV = Button(glfw.KeyV)
|
||||
KeyW = Button(glfw.KeyW)
|
||||
KeyX = Button(glfw.KeyX)
|
||||
KeyY = Button(glfw.KeyY)
|
||||
KeyZ = Button(glfw.KeyZ)
|
||||
KeyLeftBracket = Button(glfw.KeyLeftBracket)
|
||||
KeyBackslash = Button(glfw.KeyBackslash)
|
||||
KeyRightBracket = Button(glfw.KeyRightBracket)
|
||||
KeyGraveAccent = Button(glfw.KeyGraveAccent)
|
||||
KeyWorld1 = Button(glfw.KeyWorld1)
|
||||
KeyWorld2 = Button(glfw.KeyWorld2)
|
||||
KeyEscape = Button(glfw.KeyEscape)
|
||||
KeyEnter = Button(glfw.KeyEnter)
|
||||
KeyTab = Button(glfw.KeyTab)
|
||||
KeyBackspace = Button(glfw.KeyBackspace)
|
||||
KeyInsert = Button(glfw.KeyInsert)
|
||||
KeyDelete = Button(glfw.KeyDelete)
|
||||
KeyRight = Button(glfw.KeyRight)
|
||||
KeyLeft = Button(glfw.KeyLeft)
|
||||
KeyDown = Button(glfw.KeyDown)
|
||||
KeyUp = Button(glfw.KeyUp)
|
||||
KeyPageUp = Button(glfw.KeyPageUp)
|
||||
KeyPageDown = Button(glfw.KeyPageDown)
|
||||
KeyHome = Button(glfw.KeyHome)
|
||||
KeyEnd = Button(glfw.KeyEnd)
|
||||
KeyCapsLock = Button(glfw.KeyCapsLock)
|
||||
KeyScrollLock = Button(glfw.KeyScrollLock)
|
||||
KeyNumLock = Button(glfw.KeyNumLock)
|
||||
KeyPrintScreen = Button(glfw.KeyPrintScreen)
|
||||
KeyPause = Button(glfw.KeyPause)
|
||||
KeyF1 = Button(glfw.KeyF1)
|
||||
KeyF2 = Button(glfw.KeyF2)
|
||||
KeyF3 = Button(glfw.KeyF3)
|
||||
KeyF4 = Button(glfw.KeyF4)
|
||||
KeyF5 = Button(glfw.KeyF5)
|
||||
KeyF6 = Button(glfw.KeyF6)
|
||||
KeyF7 = Button(glfw.KeyF7)
|
||||
KeyF8 = Button(glfw.KeyF8)
|
||||
KeyF9 = Button(glfw.KeyF9)
|
||||
KeyF10 = Button(glfw.KeyF10)
|
||||
KeyF11 = Button(glfw.KeyF11)
|
||||
KeyF12 = Button(glfw.KeyF12)
|
||||
KeyF13 = Button(glfw.KeyF13)
|
||||
KeyF14 = Button(glfw.KeyF14)
|
||||
KeyF15 = Button(glfw.KeyF15)
|
||||
KeyF16 = Button(glfw.KeyF16)
|
||||
KeyF17 = Button(glfw.KeyF17)
|
||||
KeyF18 = Button(glfw.KeyF18)
|
||||
KeyF19 = Button(glfw.KeyF19)
|
||||
KeyF20 = Button(glfw.KeyF20)
|
||||
KeyF21 = Button(glfw.KeyF21)
|
||||
KeyF22 = Button(glfw.KeyF22)
|
||||
KeyF23 = Button(glfw.KeyF23)
|
||||
KeyF24 = Button(glfw.KeyF24)
|
||||
KeyF25 = Button(glfw.KeyF25)
|
||||
KeyKP0 = Button(glfw.KeyKP0)
|
||||
KeyKP1 = Button(glfw.KeyKP1)
|
||||
KeyKP2 = Button(glfw.KeyKP2)
|
||||
KeyKP3 = Button(glfw.KeyKP3)
|
||||
KeyKP4 = Button(glfw.KeyKP4)
|
||||
KeyKP5 = Button(glfw.KeyKP5)
|
||||
KeyKP6 = Button(glfw.KeyKP6)
|
||||
KeyKP7 = Button(glfw.KeyKP7)
|
||||
KeyKP8 = Button(glfw.KeyKP8)
|
||||
KeyKP9 = Button(glfw.KeyKP9)
|
||||
KeyKPDecimal = Button(glfw.KeyKPDecimal)
|
||||
KeyKPDivide = Button(glfw.KeyKPDivide)
|
||||
KeyKPMultiply = Button(glfw.KeyKPMultiply)
|
||||
KeyKPSubtract = Button(glfw.KeyKPSubtract)
|
||||
KeyKPAdd = Button(glfw.KeyKPAdd)
|
||||
KeyKPEnter = Button(glfw.KeyKPEnter)
|
||||
KeyKPEqual = Button(glfw.KeyKPEqual)
|
||||
KeyLeftShift = Button(glfw.KeyLeftShift)
|
||||
KeyLeftControl = Button(glfw.KeyLeftControl)
|
||||
KeyLeftAlt = Button(glfw.KeyLeftAlt)
|
||||
KeyLeftSuper = Button(glfw.KeyLeftSuper)
|
||||
KeyRightShift = Button(glfw.KeyRightShift)
|
||||
KeyRightControl = Button(glfw.KeyRightControl)
|
||||
KeyRightAlt = Button(glfw.KeyRightAlt)
|
||||
KeyRightSuper = Button(glfw.KeyRightSuper)
|
||||
KeyMenu = Button(glfw.KeyMenu)
|
||||
KeyLast = Button(glfw.KeyLast)
|
||||
)
|
||||
|
||||
// String returns a human-readable string describing the Button.
|
||||
func (b Button) String() string {
|
||||
name, ok := buttonNames[b]
|
||||
if !ok {
|
||||
return "Invalid"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
var buttonNames = map[Button]string{
|
||||
MouseButton4: "MouseButton4",
|
||||
MouseButton5: "MouseButton5",
|
||||
MouseButton6: "MouseButton6",
|
||||
MouseButton7: "MouseButton7",
|
||||
MouseButton8: "MouseButton8",
|
||||
MouseButtonLeft: "MouseButtonLeft",
|
||||
MouseButtonRight: "MouseButtonRight",
|
||||
MouseButtonMiddle: "MouseButtonMiddle",
|
||||
KeyUnknown: "Unknown",
|
||||
KeySpace: "Space",
|
||||
KeyApostrophe: "Apostrophe",
|
||||
KeyComma: "Comma",
|
||||
KeyMinus: "Minus",
|
||||
KeyPeriod: "Period",
|
||||
KeySlash: "Slash",
|
||||
Key0: "0",
|
||||
Key1: "1",
|
||||
Key2: "2",
|
||||
Key3: "3",
|
||||
Key4: "4",
|
||||
Key5: "5",
|
||||
Key6: "6",
|
||||
Key7: "7",
|
||||
Key8: "8",
|
||||
Key9: "9",
|
||||
KeySemicolon: "Semicolon",
|
||||
KeyEqual: "Equal",
|
||||
KeyA: "A",
|
||||
KeyB: "B",
|
||||
KeyC: "C",
|
||||
KeyD: "D",
|
||||
KeyE: "E",
|
||||
KeyF: "F",
|
||||
KeyG: "G",
|
||||
KeyH: "H",
|
||||
KeyI: "I",
|
||||
KeyJ: "J",
|
||||
KeyK: "K",
|
||||
KeyL: "L",
|
||||
KeyM: "M",
|
||||
KeyN: "N",
|
||||
KeyO: "O",
|
||||
KeyP: "P",
|
||||
KeyQ: "Q",
|
||||
KeyR: "R",
|
||||
KeyS: "S",
|
||||
KeyT: "T",
|
||||
KeyU: "U",
|
||||
KeyV: "V",
|
||||
KeyW: "W",
|
||||
KeyX: "X",
|
||||
KeyY: "Y",
|
||||
KeyZ: "Z",
|
||||
KeyLeftBracket: "LeftBracket",
|
||||
KeyBackslash: "Backslash",
|
||||
KeyRightBracket: "RightBracket",
|
||||
KeyGraveAccent: "GraveAccent",
|
||||
KeyWorld1: "World1",
|
||||
KeyWorld2: "World2",
|
||||
KeyEscape: "Escape",
|
||||
KeyEnter: "Enter",
|
||||
KeyTab: "Tab",
|
||||
KeyBackspace: "Backspace",
|
||||
KeyInsert: "Insert",
|
||||
KeyDelete: "Delete",
|
||||
KeyRight: "Right",
|
||||
KeyLeft: "Left",
|
||||
KeyDown: "Down",
|
||||
KeyUp: "Up",
|
||||
KeyPageUp: "PageUp",
|
||||
KeyPageDown: "PageDown",
|
||||
KeyHome: "Home",
|
||||
KeyEnd: "End",
|
||||
KeyCapsLock: "CapsLock",
|
||||
KeyScrollLock: "ScrollLock",
|
||||
KeyNumLock: "NumLock",
|
||||
KeyPrintScreen: "PrintScreen",
|
||||
KeyPause: "Pause",
|
||||
KeyF1: "F1",
|
||||
KeyF2: "F2",
|
||||
KeyF3: "F3",
|
||||
KeyF4: "F4",
|
||||
KeyF5: "F5",
|
||||
KeyF6: "F6",
|
||||
KeyF7: "F7",
|
||||
KeyF8: "F8",
|
||||
KeyF9: "F9",
|
||||
KeyF10: "F10",
|
||||
KeyF11: "F11",
|
||||
KeyF12: "F12",
|
||||
KeyF13: "F13",
|
||||
KeyF14: "F14",
|
||||
KeyF15: "F15",
|
||||
KeyF16: "F16",
|
||||
KeyF17: "F17",
|
||||
KeyF18: "F18",
|
||||
KeyF19: "F19",
|
||||
KeyF20: "F20",
|
||||
KeyF21: "F21",
|
||||
KeyF22: "F22",
|
||||
KeyF23: "F23",
|
||||
KeyF24: "F24",
|
||||
KeyF25: "F25",
|
||||
KeyKP0: "KP0",
|
||||
KeyKP1: "KP1",
|
||||
KeyKP2: "KP2",
|
||||
KeyKP3: "KP3",
|
||||
KeyKP4: "KP4",
|
||||
KeyKP5: "KP5",
|
||||
KeyKP6: "KP6",
|
||||
KeyKP7: "KP7",
|
||||
KeyKP8: "KP8",
|
||||
KeyKP9: "KP9",
|
||||
KeyKPDecimal: "KPDecimal",
|
||||
KeyKPDivide: "KPDivide",
|
||||
KeyKPMultiply: "KPMultiply",
|
||||
KeyKPSubtract: "KPSubtract",
|
||||
KeyKPAdd: "KPAdd",
|
||||
KeyKPEnter: "KPEnter",
|
||||
KeyKPEqual: "KPEqual",
|
||||
KeyLeftShift: "LeftShift",
|
||||
KeyLeftControl: "LeftControl",
|
||||
KeyLeftAlt: "LeftAlt",
|
||||
KeyLeftSuper: "LeftSuper",
|
||||
KeyRightShift: "RightShift",
|
||||
KeyRightControl: "RightControl",
|
||||
KeyRightAlt: "RightAlt",
|
||||
KeyRightSuper: "RightSuper",
|
||||
KeyMenu: "Menu",
|
||||
}
|
||||
|
||||
func (w *Window) initInput() {
|
||||
mainthread.Call(func() {
|
||||
w.window.SetMouseButtonCallback(func(_ *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
|
||||
switch action {
|
||||
case glfw.Press:
|
||||
w.tempInp.buttons[Button(button)] = true
|
||||
case glfw.Release:
|
||||
w.tempInp.buttons[Button(button)] = false
|
||||
}
|
||||
})
|
||||
|
||||
w.window.SetKeyCallback(func(_ *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
|
||||
if key == glfw.KeyUnknown {
|
||||
return
|
||||
}
|
||||
switch action {
|
||||
case glfw.Press:
|
||||
w.tempInp.buttons[Button(key)] = true
|
||||
case glfw.Release:
|
||||
w.tempInp.buttons[Button(key)] = false
|
||||
case glfw.Repeat:
|
||||
w.tempInp.repeat[Button(key)] = true
|
||||
}
|
||||
})
|
||||
|
||||
w.window.SetCursorPosCallback(func(_ *glfw.Window, x, y float64) {
|
||||
w.tempInp.mouse = pixel.V(
|
||||
x+w.bounds.Min.X,
|
||||
(w.bounds.H()-y)+w.bounds.Min.Y,
|
||||
)
|
||||
})
|
||||
|
||||
w.window.SetScrollCallback(func(_ *glfw.Window, xoff, yoff float64) {
|
||||
w.tempInp.scroll.X += xoff
|
||||
w.tempInp.scroll.Y += yoff
|
||||
})
|
||||
|
||||
w.window.SetCharCallback(func(_ *glfw.Window, r rune) {
|
||||
w.tempInp.typed += string(r)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateInput polls window events. Call this function to poll window events
|
||||
// without swapping buffers. Note that the Update method invokes UpdateInput.
|
||||
func (w *Window) UpdateInput() {
|
||||
mainthread.Call(func() {
|
||||
glfw.PollEvents()
|
||||
})
|
||||
|
||||
w.prevInp = w.currInp
|
||||
w.currInp = w.tempInp
|
||||
|
||||
w.tempInp.repeat = [KeyLast + 1]bool{}
|
||||
w.tempInp.scroll = pixel.ZV
|
||||
w.tempInp.typed = ""
|
||||
}
|
97
vendor/github.com/faiface/pixel/pixelgl/monitor.go
generated
vendored
Normal file
97
vendor/github.com/faiface/pixel/pixelgl/monitor.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/go-gl/glfw/v3.2/glfw"
|
||||
)
|
||||
|
||||
// Monitor represents a physical display attached to your computer.
|
||||
type Monitor struct {
|
||||
monitor *glfw.Monitor
|
||||
}
|
||||
|
||||
// PrimaryMonitor returns the main monitor (usually the one with the taskbar and stuff).
|
||||
func PrimaryMonitor() *Monitor {
|
||||
var monitor *glfw.Monitor
|
||||
mainthread.Call(func() {
|
||||
monitor = glfw.GetPrimaryMonitor()
|
||||
})
|
||||
return &Monitor{
|
||||
monitor: monitor,
|
||||
}
|
||||
}
|
||||
|
||||
// Monitors returns a slice of all currently available monitors.
|
||||
func Monitors() []*Monitor {
|
||||
var monitors []*Monitor
|
||||
mainthread.Call(func() {
|
||||
for _, monitor := range glfw.GetMonitors() {
|
||||
monitors = append(monitors, &Monitor{monitor: monitor})
|
||||
}
|
||||
})
|
||||
return monitors
|
||||
}
|
||||
|
||||
// Name returns a human-readable name of the Monitor.
|
||||
func (m *Monitor) Name() string {
|
||||
var name string
|
||||
mainthread.Call(func() {
|
||||
name = m.monitor.GetName()
|
||||
})
|
||||
return name
|
||||
}
|
||||
|
||||
// PhysicalSize returns the size of the display area of the Monitor in millimeters.
|
||||
func (m *Monitor) PhysicalSize() (width, height float64) {
|
||||
var wi, hi int
|
||||
mainthread.Call(func() {
|
||||
wi, hi = m.monitor.GetPhysicalSize()
|
||||
})
|
||||
width = float64(wi)
|
||||
height = float64(hi)
|
||||
return
|
||||
}
|
||||
|
||||
// Position returns the position of the upper-left corner of the Monitor in screen coordinates.
|
||||
func (m *Monitor) Position() (x, y float64) {
|
||||
var xi, yi int
|
||||
mainthread.Call(func() {
|
||||
xi, yi = m.monitor.GetPos()
|
||||
})
|
||||
x = float64(xi)
|
||||
y = float64(yi)
|
||||
return
|
||||
}
|
||||
|
||||
// Size returns the resolution of the Monitor in pixels.
|
||||
func (m *Monitor) Size() (width, height float64) {
|
||||
var mode *glfw.VidMode
|
||||
mainthread.Call(func() {
|
||||
mode = m.monitor.GetVideoMode()
|
||||
})
|
||||
width = float64(mode.Width)
|
||||
height = float64(mode.Height)
|
||||
return
|
||||
}
|
||||
|
||||
// BitDepth returns the number of bits per color of the Monitor.
|
||||
func (m *Monitor) BitDepth() (red, green, blue int) {
|
||||
var mode *glfw.VidMode
|
||||
mainthread.Call(func() {
|
||||
mode = m.monitor.GetVideoMode()
|
||||
})
|
||||
red = mode.RedBits
|
||||
green = mode.GreenBits
|
||||
blue = mode.BlueBits
|
||||
return
|
||||
}
|
||||
|
||||
// RefreshRate returns the refresh frequency of the Monitor in Hz (refreshes/second).
|
||||
func (m *Monitor) RefreshRate() (rate float64) {
|
||||
var mode *glfw.VidMode
|
||||
mainthread.Call(func() {
|
||||
mode = m.monitor.GetVideoMode()
|
||||
})
|
||||
rate = float64(mode.RefreshRate)
|
||||
return
|
||||
}
|
33
vendor/github.com/faiface/pixel/pixelgl/run.go
generated
vendored
Normal file
33
vendor/github.com/faiface/pixel/pixelgl/run.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/go-gl/glfw/v3.2/glfw"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Run is essentially the main function of PixelGL. It exists mainly due to the technical
|
||||
// limitations of OpenGL and operating systems. In short, all graphics and window manipulating calls
|
||||
// must be done from the main thread. Run makes this possible.
|
||||
//
|
||||
// Call this function from the main function of your application. This is necessary, so that Run
|
||||
// runs on the main thread.
|
||||
//
|
||||
// func run() {
|
||||
// // interact with Pixel and PixelGL from here (even concurrently)
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// pixel.Run(run)
|
||||
// }
|
||||
//
|
||||
// You can spawn any number of goroutines from your run function and interact with PixelGL
|
||||
// concurrently. The only condition is that the Run function is called from your main function.
|
||||
func Run(run func()) {
|
||||
err := glfw.Init()
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "failed to initialize GLFW"))
|
||||
}
|
||||
defer glfw.Terminate()
|
||||
mainthread.Run(run)
|
||||
}
|
15
vendor/github.com/faiface/pixel/pixelgl/util.go
generated
vendored
Normal file
15
vendor/github.com/faiface/pixel/pixelgl/util.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
)
|
||||
|
||||
func intBounds(bounds pixel.Rect) (x, y, w, h int) {
|
||||
x0 := int(math.Floor(bounds.Min.X))
|
||||
y0 := int(math.Floor(bounds.Min.Y))
|
||||
x1 := int(math.Ceil(bounds.Max.X))
|
||||
y1 := int(math.Ceil(bounds.Max.Y))
|
||||
return x0, y0, x1 - x0, y1 - y0
|
||||
}
|
426
vendor/github.com/faiface/pixel/pixelgl/window.go
generated
vendored
Normal file
426
vendor/github.com/faiface/pixel/pixelgl/window.go
generated
vendored
Normal file
@@ -0,0 +1,426 @@
|
||||
package pixelgl
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"runtime"
|
||||
|
||||
"github.com/faiface/glhf"
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/faiface/pixel"
|
||||
"github.com/go-gl/glfw/v3.2/glfw"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// WindowConfig is a structure for specifying all possible properties of a Window. Properties are
|
||||
// chosen in such a way, that you usually only need to set a few of them - defaults (zeros) should
|
||||
// usually be sensible.
|
||||
//
|
||||
// Note that you always need to set the Bounds of a Window.
|
||||
type WindowConfig struct {
|
||||
// Title at the top of the Window.
|
||||
Title string
|
||||
|
||||
// Icon specifies the icon images available to be used by the window. This is usually
|
||||
// displayed in the top bar of the window or in the task bar of the desktop environment.
|
||||
//
|
||||
// If passed one image, it will use that image, if passed an array of images those of or
|
||||
// closest to the sizes desired by the system are selected. The desired image sizes varies
|
||||
// depending on platform and system settings. The selected images will be rescaled as
|
||||
// needed. Good sizes include 16x16, 32x32 and 48x48.
|
||||
//
|
||||
// Note: Setting this value doesn't have an effect on OSX. You'll need to set the icon when
|
||||
// bundling your application for release.
|
||||
Icon []pixel.Picture
|
||||
|
||||
// Bounds specify the bounds of the Window in pixels.
|
||||
Bounds pixel.Rect
|
||||
|
||||
// If set to nil, the Window will be windowed. Otherwise it will be fullscreen on the
|
||||
// specified Monitor.
|
||||
Monitor *Monitor
|
||||
|
||||
// Whether the Window is resizable.
|
||||
Resizable bool
|
||||
|
||||
// Undecorated Window ommits the borders and decorations (close button, etc.).
|
||||
Undecorated bool
|
||||
|
||||
// VSync (vertical synchronization) synchronizes Window's framerate with the framerate of
|
||||
// the monitor.
|
||||
VSync bool
|
||||
}
|
||||
|
||||
// Window is a window handler. Use this type to manipulate a window (input, drawing, etc.).
|
||||
type Window struct {
|
||||
window *glfw.Window
|
||||
|
||||
bounds pixel.Rect
|
||||
canvas *Canvas
|
||||
vsync bool
|
||||
cursorVisible bool
|
||||
|
||||
// need to save these to correctly restore a fullscreen window
|
||||
restore struct {
|
||||
xpos, ypos, width, height int
|
||||
}
|
||||
|
||||
prevInp, currInp, tempInp struct {
|
||||
mouse pixel.Vec
|
||||
buttons [KeyLast + 1]bool
|
||||
repeat [KeyLast + 1]bool
|
||||
scroll pixel.Vec
|
||||
typed string
|
||||
}
|
||||
}
|
||||
|
||||
var currWin *Window
|
||||
|
||||
// NewWindow creates a new Window with it's properties specified in the provided config.
|
||||
//
|
||||
// If Window creation fails, an error is returned (e.g. due to unavailable graphics device).
|
||||
func NewWindow(cfg WindowConfig) (*Window, error) {
|
||||
bool2int := map[bool]int{
|
||||
true: glfw.True,
|
||||
false: glfw.False,
|
||||
}
|
||||
|
||||
w := &Window{bounds: cfg.Bounds, cursorVisible: true}
|
||||
|
||||
err := mainthread.CallErr(func() error {
|
||||
var err error
|
||||
|
||||
glfw.WindowHint(glfw.ContextVersionMajor, 3)
|
||||
glfw.WindowHint(glfw.ContextVersionMinor, 3)
|
||||
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
|
||||
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
|
||||
|
||||
glfw.WindowHint(glfw.Resizable, bool2int[cfg.Resizable])
|
||||
glfw.WindowHint(glfw.Decorated, bool2int[!cfg.Undecorated])
|
||||
|
||||
var share *glfw.Window
|
||||
if currWin != nil {
|
||||
share = currWin.window
|
||||
}
|
||||
_, _, width, height := intBounds(cfg.Bounds)
|
||||
w.window, err = glfw.CreateWindow(
|
||||
width,
|
||||
height,
|
||||
cfg.Title,
|
||||
nil,
|
||||
share,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// enter the OpenGL context
|
||||
w.begin()
|
||||
w.end()
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating window failed")
|
||||
}
|
||||
|
||||
if len(cfg.Icon) > 0 {
|
||||
imgs := make([]image.Image, len(cfg.Icon))
|
||||
for i, icon := range cfg.Icon {
|
||||
pic := pixel.PictureDataFromPicture(icon)
|
||||
imgs[i] = pic.Image()
|
||||
}
|
||||
mainthread.Call(func() {
|
||||
w.window.SetIcon(imgs)
|
||||
})
|
||||
}
|
||||
|
||||
w.SetVSync(cfg.VSync)
|
||||
|
||||
w.initInput()
|
||||
w.SetMonitor(cfg.Monitor)
|
||||
|
||||
w.canvas = NewCanvas(cfg.Bounds)
|
||||
w.Update()
|
||||
|
||||
runtime.SetFinalizer(w, (*Window).Destroy)
|
||||
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// Destroy destroys the Window. The Window can't be used any further.
|
||||
func (w *Window) Destroy() {
|
||||
mainthread.Call(func() {
|
||||
w.window.Destroy()
|
||||
})
|
||||
}
|
||||
|
||||
// Update swaps buffers and polls events. Call this method at the end of each frame.
|
||||
func (w *Window) Update() {
|
||||
mainthread.Call(func() {
|
||||
_, _, oldW, oldH := intBounds(w.bounds)
|
||||
newW, newH := w.window.GetSize()
|
||||
w.bounds = w.bounds.ResizedMin(w.bounds.Size().Add(pixel.V(
|
||||
float64(newW-oldW),
|
||||
float64(newH-oldH),
|
||||
)))
|
||||
})
|
||||
|
||||
w.canvas.SetBounds(w.bounds)
|
||||
|
||||
mainthread.Call(func() {
|
||||
w.begin()
|
||||
|
||||
framebufferWidth, framebufferHeight := w.window.GetFramebufferSize()
|
||||
glhf.Bounds(0, 0, framebufferWidth, framebufferHeight)
|
||||
|
||||
glhf.Clear(0, 0, 0, 0)
|
||||
w.canvas.gf.Frame().Begin()
|
||||
w.canvas.gf.Frame().Blit(
|
||||
nil,
|
||||
0, 0, w.canvas.Texture().Width(), w.canvas.Texture().Height(),
|
||||
0, 0, framebufferWidth, framebufferHeight,
|
||||
)
|
||||
w.canvas.gf.Frame().End()
|
||||
|
||||
if w.vsync {
|
||||
glfw.SwapInterval(1)
|
||||
} else {
|
||||
glfw.SwapInterval(0)
|
||||
}
|
||||
w.window.SwapBuffers()
|
||||
w.end()
|
||||
})
|
||||
|
||||
w.UpdateInput()
|
||||
}
|
||||
|
||||
// SetClosed sets the closed flag of the Window.
|
||||
//
|
||||
// This is useful when overriding the user's attempt to close the Window, or just to close the
|
||||
// Window from within the program.
|
||||
func (w *Window) SetClosed(closed bool) {
|
||||
mainthread.Call(func() {
|
||||
w.window.SetShouldClose(closed)
|
||||
})
|
||||
}
|
||||
|
||||
// Closed returns the closed flag of the Window, which reports whether the Window should be closed.
|
||||
//
|
||||
// The closed flag is automatically set when a user attempts to close the Window.
|
||||
func (w *Window) Closed() bool {
|
||||
var closed bool
|
||||
mainthread.Call(func() {
|
||||
closed = w.window.ShouldClose()
|
||||
})
|
||||
return closed
|
||||
}
|
||||
|
||||
// SetTitle changes the title of the Window.
|
||||
func (w *Window) SetTitle(title string) {
|
||||
mainthread.Call(func() {
|
||||
w.window.SetTitle(title)
|
||||
})
|
||||
}
|
||||
|
||||
// SetBounds sets the bounds of the Window in pixels. Bounds can be fractional, but the actual size
|
||||
// of the window will be rounded to integers.
|
||||
func (w *Window) SetBounds(bounds pixel.Rect) {
|
||||
w.bounds = bounds
|
||||
mainthread.Call(func() {
|
||||
_, _, width, height := intBounds(bounds)
|
||||
w.window.SetSize(width, height)
|
||||
})
|
||||
}
|
||||
|
||||
// SetPos sets the position, in screen coordinates, of the upper-left corner
|
||||
// of the client area of the window. Position can be fractional, but the actual position
|
||||
// of the window will be rounded to integers.
|
||||
//
|
||||
// If it is a full screen window, this function does nothing.
|
||||
func (w *Window) SetPos(pos pixel.Vec) {
|
||||
mainthread.Call(func() {
|
||||
left, top := int(pos.X), int(pos.Y)
|
||||
w.window.SetPos(left, top)
|
||||
})
|
||||
}
|
||||
|
||||
// GetPos gets the position, in screen coordinates, of the upper-left corner
|
||||
// of the client area of the window. The position is rounded to integers.
|
||||
func (w *Window) GetPos() pixel.Vec {
|
||||
var v pixel.Vec
|
||||
mainthread.Call(func() {
|
||||
x, y := w.window.GetPos()
|
||||
v = pixel.V(float64(x), float64(y))
|
||||
})
|
||||
return v
|
||||
}
|
||||
|
||||
// Bounds returns the current bounds of the Window.
|
||||
func (w *Window) Bounds() pixel.Rect {
|
||||
return w.bounds
|
||||
}
|
||||
|
||||
func (w *Window) setFullscreen(monitor *Monitor) {
|
||||
mainthread.Call(func() {
|
||||
w.restore.xpos, w.restore.ypos = w.window.GetPos()
|
||||
w.restore.width, w.restore.height = w.window.GetSize()
|
||||
|
||||
mode := monitor.monitor.GetVideoMode()
|
||||
|
||||
w.window.SetMonitor(
|
||||
monitor.monitor,
|
||||
0,
|
||||
0,
|
||||
mode.Width,
|
||||
mode.Height,
|
||||
mode.RefreshRate,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func (w *Window) setWindowed() {
|
||||
mainthread.Call(func() {
|
||||
w.window.SetMonitor(
|
||||
nil,
|
||||
w.restore.xpos,
|
||||
w.restore.ypos,
|
||||
w.restore.width,
|
||||
w.restore.height,
|
||||
0,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// SetMonitor sets the Window fullscreen on the given Monitor. If the Monitor is nil, the Window
|
||||
// will be restored to windowed state instead.
|
||||
//
|
||||
// The Window will be automatically set to the Monitor's resolution. If you want a different
|
||||
// resolution, you will need to set it manually with SetBounds method.
|
||||
func (w *Window) SetMonitor(monitor *Monitor) {
|
||||
if w.Monitor() != monitor {
|
||||
if monitor != nil {
|
||||
w.setFullscreen(monitor)
|
||||
} else {
|
||||
w.setWindowed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Monitor returns a monitor the Window is fullscreen on. If the Window is not fullscreen, this
|
||||
// function returns nil.
|
||||
func (w *Window) Monitor() *Monitor {
|
||||
var monitor *glfw.Monitor
|
||||
mainthread.Call(func() {
|
||||
monitor = w.window.GetMonitor()
|
||||
})
|
||||
if monitor == nil {
|
||||
return nil
|
||||
}
|
||||
return &Monitor{
|
||||
monitor: monitor,
|
||||
}
|
||||
}
|
||||
|
||||
// Focused returns true if the Window has input focus.
|
||||
func (w *Window) Focused() bool {
|
||||
var focused bool
|
||||
mainthread.Call(func() {
|
||||
focused = w.window.GetAttrib(glfw.Focused) == glfw.True
|
||||
})
|
||||
return focused
|
||||
}
|
||||
|
||||
// SetVSync sets whether the Window's Update should synchronize with the monitor refresh rate.
|
||||
func (w *Window) SetVSync(vsync bool) {
|
||||
w.vsync = vsync
|
||||
}
|
||||
|
||||
// VSync returns whether the Window is set to synchronize with the monitor refresh rate.
|
||||
func (w *Window) VSync() bool {
|
||||
return w.vsync
|
||||
}
|
||||
|
||||
// SetCursorVisible sets the visibility of the mouse cursor inside the Window client area.
|
||||
func (w *Window) SetCursorVisible(visible bool) {
|
||||
w.cursorVisible = visible
|
||||
mainthread.Call(func() {
|
||||
if visible {
|
||||
w.window.SetInputMode(glfw.CursorMode, glfw.CursorNormal)
|
||||
} else {
|
||||
w.window.SetInputMode(glfw.CursorMode, glfw.CursorHidden)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// CursorVisible returns the visibility status of the mouse cursor.
|
||||
func (w *Window) CursorVisible() bool {
|
||||
return w.cursorVisible
|
||||
}
|
||||
|
||||
// Note: must be called inside the main thread.
|
||||
func (w *Window) begin() {
|
||||
if currWin != w {
|
||||
w.window.MakeContextCurrent()
|
||||
glhf.Init()
|
||||
currWin = w
|
||||
}
|
||||
}
|
||||
|
||||
// Note: must be called inside the main thread.
|
||||
func (w *Window) end() {
|
||||
// nothing, really
|
||||
}
|
||||
|
||||
// MakeTriangles generates a specialized copy of the supplied Triangles that will draw onto this
|
||||
// Window.
|
||||
//
|
||||
// Window supports TrianglesPosition, TrianglesColor and TrianglesPicture.
|
||||
func (w *Window) MakeTriangles(t pixel.Triangles) pixel.TargetTriangles {
|
||||
return w.canvas.MakeTriangles(t)
|
||||
}
|
||||
|
||||
// MakePicture generates a specialized copy of the supplied Picture that will draw onto this Window.
|
||||
//
|
||||
// Window supports PictureColor.
|
||||
func (w *Window) MakePicture(p pixel.Picture) pixel.TargetPicture {
|
||||
return w.canvas.MakePicture(p)
|
||||
}
|
||||
|
||||
// SetMatrix sets a Matrix that every point will be projected by.
|
||||
func (w *Window) SetMatrix(m pixel.Matrix) {
|
||||
w.canvas.SetMatrix(m)
|
||||
}
|
||||
|
||||
// SetColorMask sets a global color mask for the Window.
|
||||
func (w *Window) SetColorMask(c color.Color) {
|
||||
w.canvas.SetColorMask(c)
|
||||
}
|
||||
|
||||
// SetComposeMethod sets a Porter-Duff composition method to be used in the following draws onto
|
||||
// this Window.
|
||||
func (w *Window) SetComposeMethod(cmp pixel.ComposeMethod) {
|
||||
w.canvas.SetComposeMethod(cmp)
|
||||
}
|
||||
|
||||
// SetSmooth sets whether the stretched Pictures drawn onto this Window should be drawn smooth or
|
||||
// pixely.
|
||||
func (w *Window) SetSmooth(smooth bool) {
|
||||
w.canvas.SetSmooth(smooth)
|
||||
}
|
||||
|
||||
// Smooth returns whether the stretched Pictures drawn onto this Window are set to be drawn smooth
|
||||
// or pixely.
|
||||
func (w *Window) Smooth() bool {
|
||||
return w.canvas.Smooth()
|
||||
}
|
||||
|
||||
// Clear clears the Window with a single color.
|
||||
func (w *Window) Clear(c color.Color) {
|
||||
w.canvas.Clear(c)
|
||||
}
|
||||
|
||||
// Color returns the color of the pixel over the given position inside the Window.
|
||||
func (w *Window) Color(at pixel.Vec) pixel.RGBA {
|
||||
return w.canvas.Color(at)
|
||||
}
|
Reference in New Issue
Block a user