ichigo/engine/asset.go

95 lines
1.9 KiB
Go
Raw Normal View History

2021-07-30 17:26:23 +10:00
package engine
2021-07-31 16:38:54 +10:00
import (
"encoding/gob"
2021-07-31 16:38:54 +10:00
"image"
2021-08-23 10:09:49 +10:00
"io/fs"
2021-07-31 20:06:49 +10:00
"log"
2021-07-31 16:38:54 +10:00
"github.com/hajimehoshi/ebiten/v2"
)
var (
2021-07-31 21:23:58 +10:00
// AnimDefs are easier to write as Go expressions -
// so just set this.
2021-08-22 20:28:25 +10:00
// TODO: put in Game
2021-08-01 14:41:39 +10:00
AnimDefs map[string]*AnimDef
2021-07-31 21:23:58 +10:00
imageCache = make(map[assetKey]*ebiten.Image)
2021-08-20 15:01:31 +10:00
2021-08-23 11:02:24 +10:00
// Ensure ImageRef satisfies interfaces.
2021-08-20 17:05:47 +10:00
_ Loader = &ImageRef{}
2021-07-31 16:38:54 +10:00
)
2021-07-30 17:26:23 +10:00
2021-08-20 16:23:10 +10:00
func init() {
gob.Register(AnimRef{})
gob.Register(ImageRef{})
gob.Register(SceneRef{})
}
type assetKey struct {
assets fs.FS
path string
}
2021-07-31 21:23:58 +10:00
// AnimRef manages an Anim using a premade AnimDef from the cache.
2021-07-31 17:15:32 +10:00
type AnimRef struct {
2021-07-31 21:23:58 +10:00
Key string
2021-07-31 17:15:32 +10:00
2021-07-31 19:49:24 +10:00
anim *Anim
2021-07-31 17:15:32 +10:00
}
2021-07-31 20:06:49 +10:00
func (r *AnimRef) Anim() *Anim {
2021-07-31 19:49:24 +10:00
if r.anim != nil {
2021-07-31 20:06:49 +10:00
return r.anim
2021-07-31 17:17:26 +10:00
}
2021-08-12 14:45:23 +10:00
ad := AnimDefs[r.Key]
if ad == nil {
log.Fatalf("Unknown AnimDef %q", r.Key)
return nil
2021-07-31 19:49:24 +10:00
}
2021-08-12 14:45:23 +10:00
r.anim = &Anim{Def: ad}
return r.anim
2021-07-31 17:17:26 +10:00
}
2021-07-31 17:15:32 +10:00
// ImageRef loads images from the AssetFS into *ebiten.Image form.
// It is your responsibility to import _ "image/..." for whatever
2021-08-20 17:05:47 +10:00
// format the files are in, and to load it (either return it as a
// subcomponent from Scan so that Game will Load it, or call Load
// yourself).
2021-07-30 17:26:23 +10:00
type ImageRef struct {
Path string
image *ebiten.Image
}
2021-08-20 17:05:47 +10:00
// Image returns the image, or nil if not loaded.
2021-07-31 17:15:32 +10:00
// Multiple distinct ImageRefs can use the same path.
2021-07-31 20:06:49 +10:00
func (r *ImageRef) Image() *ebiten.Image {
2021-08-20 17:05:47 +10:00
return r.image
}
// Load loads the image. Load is required before Image returns.
// Loading the same path multiple times uses a cache to return
// the same image.
2021-08-23 10:09:49 +10:00
func (r *ImageRef) Load(assets fs.FS) error {
2021-08-20 17:05:47 +10:00
// Fast path load from cache
r.image = imageCache[assetKey{assets, r.Path}]
2021-07-31 16:38:54 +10:00
if r.image != nil {
2021-08-20 17:05:47 +10:00
return nil
2021-07-31 16:38:54 +10:00
}
2021-08-20 17:05:47 +10:00
// Slow path
2021-08-23 10:09:49 +10:00
f, err := assets.Open(r.Path)
2021-07-31 16:38:54 +10:00
if err != nil {
2021-08-20 17:05:47 +10:00
return err
2021-07-31 16:38:54 +10:00
}
defer f.Close()
i, _, err := image.Decode(f)
if err != nil {
2021-08-20 17:05:47 +10:00
return err
2021-07-30 17:26:23 +10:00
}
2021-07-31 16:38:54 +10:00
r.image = ebiten.NewImageFromImage(i)
imageCache[assetKey{assets, r.Path}] = r.image
2021-08-20 15:52:01 +10:00
return nil
2021-08-20 15:01:31 +10:00
}