Files
aego/asset/pipeline/texture_source.go
sanspie a6822156cd
ci-platforms / windows amd64 smoke (push) Skipped
ci / release (push) Successful in 8m58s
ci-platforms / darwin amd64 smoke (push) Skipped
ci-platforms / darwin arm64 smoke (push) Skipped
ci / checks (push) Successful in 4m46s
ci / build (amd64, linux, ubuntu-24.04) (push) Successful in 13m28s
Finish Stage 12 editor fixes and refreshed platformer
2026-11-05 17:36:42 +03:00

91 lines
2.4 KiB
Go

package pipeline
import (
"bytes"
"image/png"
"io"
"os"
"strings"
"aego/asset"
"aego/core/ids"
"aego/engine/res"
)
// TextureSourceInfo resolves source metadata (including a dirty editor overlay)
// for semantic mutations. Runtime code must use TextureMetadataSource instead.
func (p *Pipeline) TextureSourceInfo(id ids.AssetID, overlay func(string) ([]byte, bool)) (asset.TextureSourceInfo, bool) {
p.mu.RLock()
defer p.mu.RUnlock()
name, ok := p.pathOf(id)
if !ok && overlay != nil {
// Newly sliced frames already have stable IDs in dirty metadata, before
// Save adds them to the persistent import index.
for _, record := range p.byID {
if record.importer.ID() != "texture" {
continue
}
encoded, present := overlay(record.path + MetaSuffix)
if !present {
continue
}
meta, err := ParseMeta(encoded, record.path+MetaSuffix)
if err != nil || meta.ID != record.id {
continue
}
if frame, exists := meta.Frame(id); exists {
if ok {
return asset.TextureSourceInfo{}, false
}
name, ok = record.path+SubSep+frame.Name, true
}
}
}
if !ok {
return asset.TextureSourceInfo{}, false
}
source, _, _ := strings.Cut(name, SubSep)
read := func(name string) ([]byte, error) {
if overlay != nil {
if b, ok := overlay(name); ok {
return b, nil
}
}
return p.read(name)
}
// Schema and channel pickers need dimensions, not the full image: stream bounded disk reads and avoid a second full copy of dirty bytes in the overlay.
var sourceReader io.Reader
if overlay != nil {
if data, present := overlay(source); present {
sourceReader = bytes.NewReader(data)
}
}
if sourceReader == nil {
var file io.ReadCloser
var err error
if embedded, ok := strings.CutPrefix(source, "engine://"); ok {
file, err = res.FS().Open(embedded)
} else {
file, err = os.Open(p.Abs(source))
}
if err != nil {
return asset.TextureSourceInfo{}, false
}
defer file.Close()
sourceReader = file
}
config, err := png.DecodeConfig(io.LimitReader(sourceReader, 32<<20))
if err != nil {
return asset.TextureSourceInfo{}, false
}
encoded, err := read(source + MetaSuffix)
if err != nil {
return asset.TextureSourceInfo{}, false
}
meta, err := ParseMeta(encoded, source+MetaSuffix)
if err != nil {
return asset.TextureSourceInfo{}, false
}
return asset.TextureSource(meta, source, config.Width, config.Height, id)
}