Skip to content

Commit

Permalink
Using pixelutils packer to handle images
Browse files Browse the repository at this point in the history
  • Loading branch information
Allen Ray committed Jul 30, 2020
1 parent b9122bd commit 81a64e6
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 49 deletions.
5 changes: 5 additions & 0 deletions font.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"log"
"unsafe"

"github.com/inkyblackness/imgui-go"

"github.com/faiface/pixel"
)

Expand All @@ -22,6 +24,9 @@ func (ui *UI) loadFont() {
}

ui.fontAtlas = ui.win.MakePicture(pic)
id, _ := ui.packer.Insert(pixel.NewSprite(pic, pic.Bounds()))
ui.fontId = id
ui.fonts.SetTextureID(imgui.TextureID(id))
}

// loadDefaultFont loads the imgui default font if the user wants it.
Expand Down
48 changes: 48 additions & 0 deletions geo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package pixelui

import (
"github.com/faiface/pixel"
"github.com/inkyblackness/imgui-go"
)

// imguiRectToPixelRect Converts the imgui rect to a Pixel rect
func imguiRectToPixelRect(r imgui.Vec4) pixel.Rect {
return pixel.R(float64(r.X), float64(r.Y), float64(r.Z), float64(r.W))
}

// IVec converts a pixel vector to an imgui vector
func IVec(v pixel.Vec) imgui.Vec2 {
return imgui.Vec2{X: float32(v.X), Y: float32(v.Y)}
}

// IV creates an imgui vector from the given points.
func IV(x, y float64) imgui.Vec2 {
return imgui.Vec2{X: float32(x), Y: float32(y)}
}

// PV converts an imgui vector to a pixel vector
func PV(v imgui.Vec2) pixel.Vec {
return pixel.V(float64(v.X), float64(v.Y))
}

// ProjectVec projects the vector by the UI's matrix (vertical flip)
// and returns that as a imgui vector
func ProjectVec(v pixel.Vec) imgui.Vec2 {
return IVec(currentUI.matrix.Project(v))
}

// ProjectV creates a pixel vector and projects it using ProjectVec
func ProjectV(x, y float64) imgui.Vec2 {
return ProjectVec(pixel.V(x, y))
}

// UnprojectV unprojects the vector by the UI's matrix (vertical flip)
// and returns that as a pixel vector
func UnprojectV(v imgui.Vec2) pixel.Vec {
return currentUI.matrix.Unproject(PV(v))
}

// IZV returns an imgui zero vector
func IZV() imgui.Vec2 {
return imgui.Vec2{X: 0, Y: 0}
}
34 changes: 34 additions & 0 deletions sprite.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package pixelui

import (
"unsafe"

"github.com/dusk125/pixelutils/packer"
"github.com/inkyblackness/imgui-go"

"github.com/faiface/pixel"
)

const (
WrappedNone = iota
WrappedSprite
WrappedBatch
WrappedCanvas
)

type wrapper struct {
Type int
Value interface{}
}

func Sprite(sprite *pixel.Sprite) imgui.TextureID {
return imgui.TextureID(unsafe.Pointer(&wrapper{
Type: WrappedSprite,
Value: sprite,
}))
}

func (ui *UI) AddSprite(sprite *pixel.Sprite) imgui.TextureID {
id, _ := ui.packer.InsertV(sprite, packer.InsertFlipped)
return imgui.TextureID(id)
}
93 changes: 44 additions & 49 deletions ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"
"unsafe"

"github.com/dusk125/pixelutils/packer"
"github.com/faiface/mainthread"
"github.com/faiface/pixel/pixelgl"
)
Expand All @@ -32,7 +33,15 @@ uniform vec4 uClipRect;
void main() {
if ((vClipRect != vec4(0,0,0,0)) && (gl_FragCoord.x < vClipRect.x || gl_FragCoord.y < vClipRect.y || gl_FragCoord.x > vClipRect.z || gl_FragCoord.y > vClipRect.w))
discard;
fragColor *= vColor * texture(uTexture, vTexCoords).a;
if (vIntensity == 0) {
fragColor *= vColor * texture(uTexture, vTexCoords).a;
fragColor *= uColorMask;
} else {
fragColor = vec4(0, 0, 0, 0);
fragColor += vColor;
fragColor *= vColor * texture(uTexture, vTexCoords);
fragColor *= uColorMask;
}
}
`

Expand All @@ -47,18 +56,20 @@ type UI struct {
shader *pixelgl.GLShader
matrix pixel.Matrix
shaderTris *pixelgl.GLTriangles
packer *packer.Packer
fontId int
}

var currentUI *UI

// pixelui.NewUI flags:
// NO_DEFAULT_FONT: Do not load the default font during NewUI.
const (
NO_DEFAULT_FONT = 0x0001
NO_DEFAULT_FONT uint8 = 1 << iota
)

// NewUI Creates the UI and setups up its internal structures
func NewUI(win *pixelgl.Window, flags int) *UI {
func NewUI(win *pixelgl.Window, flags uint8) *UI {
var context *imgui.Context
mainthread.Call(func() {
context = imgui.CreateContext(nil)
Expand All @@ -70,6 +81,8 @@ func NewUI(win *pixelgl.Window, flags int) *UI {
}
currentUI = ui

ui.packer = packer.NewPacker(4069, 4096, 0)

ui.matrix = pixel.IM.ScaledXY(win.Bounds().Center(), pixel.V(1, -1))

ui.io = imgui.CurrentIO()
Expand All @@ -89,6 +102,10 @@ func NewUI(win *pixelgl.Window, flags int) *UI {
return ui
}

func (ui UI) GetPacker() *packer.Packer {
return ui.packer
}

// Destroy cleans up the imgui context
func (ui *UI) Destroy() {
ui.context.Destroy()
Expand All @@ -112,6 +129,7 @@ func (ui *UI) update() {
// Draw Draws the imgui UI to the Pixel Window
func (ui *UI) Draw(win *pixelgl.Window) {
win.SetComposeMethod(pixel.ComposeOver)
win.SetMatrix(ui.matrix)

// imgui draws things from top-left as 0,0 where Pixel draws from bottom-left as 0,0,
// for drawing and handling inputs, we need to "flip" imgui.
Expand Down Expand Up @@ -155,6 +173,14 @@ func (ui *UI) Draw(win *pixelgl.Window) {
clipRect.Max = ui.matrix.Project(clipRect.Max)
clipRect = clipRect.Norm()

id := int(cmd.TextureID())
texRect := ui.packer.BoundsOf(id)

intensity := 0.0
if id != ui.fontId {
intensity = 1.0
}

for i := 0; i < count; i++ {
idx := unsafe.Pointer(uintptr(idxStart) + indexBufferOffset)
index := *(*uint16)(idx)
Expand All @@ -165,10 +191,10 @@ func (ui *UI) Draw(win *pixelgl.Window) {

position := PV(*pos)
color := imguiColorToPixelColor(*col)
uuvv := PV(*uv)
uuvv := ui.calcData(texRect, PV(*uv))

ui.shaderTris.SetPosition(iStart+i, position)
ui.shaderTris.SetPicture(iStart+i, uuvv, 0)
ui.shaderTris.SetPicture(iStart+i, uuvv, intensity)
ui.shaderTris.SetColor(iStart+i, pixel.ToRGBA(color))
ui.shaderTris.SetClipRect(iStart+i, clipRect)
indexBufferOffset += uintptr(indexSize)
Expand All @@ -179,12 +205,23 @@ func (ui *UI) Draw(win *pixelgl.Window) {

ui.shaderTris.SetLen(totalTris)
ui.shaderTris.CopyVertices()
ui.fontAtlas.Draw(win.MakeTriangles(ui.shaderTris))
win.MakePicture(ui.packer.Picture()).Draw(win.MakeTriangles(ui.shaderTris))

win.SetMatrix(pixel.IM)
// ui.packer.Draw(win, pixel.IM.Moved(ui.packer.Center()))
}

// imguiColorToPixelColor Converts the imgui color to a Pixel color
// recip returns the reciprocal of the given number.
func recip(m float64) float64 {
return 1 / m
}

// calcData scales the incoming sprite uv to the proper sub-sprite in the packed atlas.
func (ui *UI) calcData(frame pixel.Rect, uuvv pixel.Vec) (pic pixel.Vec) {
return uuvv.ScaledXY(frame.Size()).Add(frame.Min).ScaledXY(ui.packer.Bounds().Size().Map(recip))
}

// imguiColorToPixelColor Converts the imgui color to a Pixel color.
func imguiColorToPixelColor(c uint32) color.RGBA {
// ABGR -> RGBA
return color.RGBA{
Expand All @@ -194,45 +231,3 @@ func imguiColorToPixelColor(c uint32) color.RGBA {
R: uint8(c & 0xFF),
}
}

// imguiRectToPixelRect Converts the imgui rect to a Pixel rect
func imguiRectToPixelRect(r imgui.Vec4) pixel.Rect {
return pixel.R(float64(r.X), float64(r.Y), float64(r.Z), float64(r.W))
}

// IVec converts a pixel vector to an imgui vector
func IVec(v pixel.Vec) imgui.Vec2 {
return imgui.Vec2{X: float32(v.X), Y: float32(v.Y)}
}

// IV creates an imgui vector from the given points.
func IV(x, y float64) imgui.Vec2 {
return imgui.Vec2{X: float32(x), Y: float32(y)}
}

// PV converts an imgui vector to a pixel vector
func PV(v imgui.Vec2) pixel.Vec {
return pixel.V(float64(v.X), float64(v.Y))
}

// ProjectVec projects the vector by the UI's matrix (vertical flip)
// and returns that as a imgui vector
func ProjectVec(v pixel.Vec) imgui.Vec2 {
return IVec(currentUI.matrix.Project(v))
}

// ProjectV creates a pixel vector and projects it using ProjectVec
func ProjectV(x, y float64) imgui.Vec2 {
return ProjectVec(pixel.V(x, y))
}

// UnprojectV unprojects the vector by the UI's matrix (vertical flip)
// and returns that as a pixel vector
func UnprojectV(v imgui.Vec2) pixel.Vec {
return currentUI.matrix.Unproject(PV(v))
}

// IZV returns an imgui zero vector
func IZV() imgui.Vec2 {
return imgui.Vec2{X: 0, Y: 0}
}

0 comments on commit 81a64e6

Please sign in to comment.