package assetstore import ( "fmt" "image" "log" "path/filepath" "strings" "github.com/hajimehoshi/ebiten" "code.ur.gs/lupine/ordoor/internal/data" ) type Object struct { assets *AssetStore sprites []*Sprite raw *data.Object NumSprites int Name string } type Sprite struct { obj *Object XOffset int // TODO: replace these everywhere with Rect YOffset int Width int Height int ID string Rect image.Rectangle Image *ebiten.Image } func (a *AssetStore) Object(name string) (*Object, error) { name = canonical(name) if obj, ok := a.objs[name]; ok { return obj, nil } log.Printf("Loading object %v", name) filename, err := a.lookup(name, "obj", "Obj") if err != nil { return nil, err } obj, err := a.ObjectByPath(filename) if err != nil { return nil, err } a.objs[name] = obj return obj, nil } // FIXME: Objects loaded by path are not cached func (a *AssetStore) ObjectByPath(path string) (*Object, error) { name := filepath.Base(path) name = strings.Replace(name, filepath.Ext(name), "", -1) name = canonical(name) raw, err := data.LoadObjectLazily(path) if err != nil { return nil, err } obj := &Object{ assets: a, sprites: make([]*Sprite, int(raw.NumSprites)), raw: raw, NumSprites: int(raw.NumSprites), Name: canonical(name), } return obj, nil } // Loads all sprites in the object eagerly func (o *Object) LoadSprites() error { for i := 0; i < o.NumSprites; i++ { if _, err := o.Sprite(i); err != nil { return err } } return nil } func (o *Object) Sprites(start, count int) ([]*Sprite, error) { out := make([]*Sprite, count) for i := start; i < start+count; i++ { sprite, err := o.Sprite(i) if err != nil { return nil, err } out[i-start] = sprite } return out, nil } func (o *Object) Sprite(idx int) (*Sprite, error) { if sprite := o.sprites[idx]; sprite != nil { return sprite, nil } if o.raw.Sprites[idx] == nil { if err := o.raw.LoadSprite(idx); err != nil { return nil, err } } raw := o.raw.Sprites[idx] img, err := ebiten.NewImageFromImage(raw.ToImage(o.assets.Palette), ebiten.FilterDefault) if err != nil { return nil, err } rect := image.Rect( int(raw.XOffset), int(raw.YOffset), int(raw.XOffset+raw.Width), int(raw.YOffset+raw.Height), ) sprite := &Sprite{ ID: fmt.Sprintf("%v:%v", o.raw.Name, idx), obj: o, Width: rect.Dx(), Height: rect.Dy(), XOffset: rect.Min.X, YOffset: rect.Min.Y, Rect: rect, Image: img, } o.sprites[idx] = sprite return sprite, nil }