graphics: Add EBITEN_DUMP_IMAGES_KEY

Fixes #589
This commit is contained in:
Hajime Hoshi 2018-04-28 21:49:00 +09:00
parent eb357f61b5
commit 613f384cb5
4 changed files with 123 additions and 10 deletions

5
doc.go
View File

@ -37,9 +37,12 @@
// ebiten.Run(update, 320, 240, 2, "Your game's title") // ebiten.Run(update, 320, 240, 2, "Your game's title")
// } // }
// //
// The EBITEN_SCREENSHOT_KEY environment variable specified the key // The EBITEN_SCREENSHOT_KEY environment variable specifies the key
// to take a screenshot. For example, if you run your game with // to take a screenshot. For example, if you run your game with
// `EBITEN_SCREENSHOT_KEY=q`, you can take a game screen's screenshot // `EBITEN_SCREENSHOT_KEY=q`, you can take a game screen's screenshot
// by pressing Q key. The image file is saved at the current directory // by pressing Q key. The image file is saved at the current directory
// with the name screen*.png. // with the name screen*.png.
//
// The EBITEN_DUMP_IMAGES_KEY environment variable specifies the key
// to dump all the internal images.
package ebiten package ebiten

View File

@ -15,6 +15,8 @@
package restorable package restorable
import ( import (
"image"
"github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/graphics"
) )
@ -71,6 +73,39 @@ func Restore() error {
return theImages.restore() return theImages.restore()
} }
func Images() ([]image.Image, error) {
var imgs []image.Image
for img := range theImages.images {
if img.volatile {
continue
}
if img.screen {
continue
}
w, h := img.Size()
pix := make([]byte, 4*w*h)
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
c, err := img.At(i, j)
if err != nil {
return nil, err
}
pix[4*(i+j*w)] = byte(c.R)
pix[4*(i+j*w)+1] = byte(c.G)
pix[4*(i+j*w)+2] = byte(c.B)
pix[4*(i+j*w)+3] = byte(c.A)
}
}
imgs = append(imgs, &image.RGBA{
Pix: pix,
Stride: 4 * w,
Rect: image.Rect(0, 0, w, h),
})
}
return imgs, nil
}
// add adds img to the images. // add adds img to the images.
func (i *images) add(img *Image) { func (i *images) add(img *Image) {
i.images[img] = struct{}{} i.images[img] = struct{}{}

View File

@ -16,6 +16,7 @@ package shareable
import ( import (
"fmt" "fmt"
"image"
"image/color" "image/color"
"runtime" "runtime"
@ -322,3 +323,9 @@ func BackendNumForTesting() int {
defer backendsM.Unlock() defer backendsM.Unlock()
return len(theBackends) return len(theBackends)
} }
func Images() ([]image.Image, error) {
backendsM.Lock()
defer backendsM.Unlock()
return restorable.Images()
}

78
run.go
View File

@ -17,12 +17,15 @@ package ebiten
import ( import (
"fmt" "fmt"
"image" "image"
"io/ioutil"
"os" "os"
"path/filepath"
"sync/atomic" "sync/atomic"
"github.com/hajimehoshi/ebiten/internal/clock" "github.com/hajimehoshi/ebiten/internal/clock"
"github.com/hajimehoshi/ebiten/internal/devicescale" "github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/png" "github.com/hajimehoshi/ebiten/internal/png"
"github.com/hajimehoshi/ebiten/internal/shareable"
"github.com/hajimehoshi/ebiten/internal/ui" "github.com/hajimehoshi/ebiten/internal/ui"
) )
@ -99,6 +102,10 @@ type imageDumper struct {
hasScreenshotKey bool hasScreenshotKey bool
screenshotKey Key screenshotKey Key
toTakeScreenshot bool toTakeScreenshot bool
hasDumpImagesKey bool
dumpImagesKey Key
toDumpImages bool
} }
func (i *imageDumper) update(screen *Image) error { func (i *imageDumper) update(screen *Image) error {
@ -116,18 +123,43 @@ func (i *imageDumper) update(screen *Image) error {
i.screenshotKey = key i.screenshotKey = key
} }
} }
if keyname := os.Getenv("EBITEN_DUMP_IMAGES_KEY"); keyname != "" {
if key, ok := keyNameToKey(keyname); ok {
i.hasDumpImagesKey = true
i.dumpImagesKey = key
}
}
} }
if i.hasScreenshotKey && IsKeyPressed(i.screenshotKey) { keys := map[Key]struct{}{}
i.keyState[i.screenshotKey]++ if i.hasScreenshotKey {
if i.keyState[i.screenshotKey] == 1 { keys[i.screenshotKey] = struct{}{}
}
if i.hasDumpImagesKey {
keys[i.dumpImagesKey] = struct{}{}
}
for key := range keys {
if IsKeyPressed(key) {
i.keyState[key]++
if i.keyState[key] == 1 {
if i.hasScreenshotKey && key == i.screenshotKey {
i.toTakeScreenshot = true i.toTakeScreenshot = true
} }
if i.hasDumpImagesKey && key == i.dumpImagesKey {
i.toDumpImages = true
}
}
} else { } else {
i.keyState[i.screenshotKey] = 0 i.keyState[key] = 0
}
} }
if i.toTakeScreenshot && !IsRunningSlowly() { if IsRunningSlowly() {
return nil
}
if i.toTakeScreenshot {
filename := "screenshot.png" filename := "screenshot.png"
idx := 0 idx := 0
for { for {
@ -148,6 +180,42 @@ func (i *imageDumper) update(screen *Image) error {
} }
i.toTakeScreenshot = false i.toTakeScreenshot = false
} }
if i.toDumpImages {
dir, err := ioutil.TempDir("", "ebiten_textures")
if err != nil {
return err
}
dump := func(img image.Image, index int) error {
filename := filepath.Join(dir, fmt.Sprintf("%d.png", index))
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
if err := png.Encode(f, img); err != nil {
return err
}
return nil
}
images, err := shareable.Images()
if err != nil {
return err
}
for i, img := range images {
if err := dump(img, i); err != nil {
return err
}
}
i.toDumpImages = false
fmt.Fprintf(os.Stderr, "Dumped texture at: %s\n", dir)
}
return nil return nil
} }