Files
aego/asset/pipeline/settings.go
T
sanspie 5eb1832907
ci-platforms / darwin amd64 smoke (push) Skipped
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 15m28s
ci / release (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
ci-platforms / darwin arm64 smoke (push) Skipped
ci / checks (push) Successful in 7m47s
Complete Stage 12 for v0.12.0
2026-11-05 11:46:53 +03:00

147 lines
4.2 KiB
Go

package pipeline
import (
"bytes"
"slices"
"strings"
"aego/core/errs"
"aego/core/ids"
"aego/core/log"
"aego/project"
)
func (p *Pipeline) MetaOf(id ids.AssetID) (Meta, bool) {
p.mu.RLock()
defer p.mu.RUnlock()
r := p.byID[id]
if r == nil || r.meta == nil {
return Meta{}, false
}
m := *r.meta
m.Settings = r.meta.Settings.Clone()
m.Subs = slices.Clone(r.meta.Subs)
return m, true
}
// SetSubs writes the cells of a sliced sheet into its meta; the next import turns them into sprite assets (D339).
func (p *Pipeline) SetSubs(id ids.AssetID, subs []SubAsset) error {
p.mu.Lock()
defer p.mu.Unlock()
if p.shared {
return errs.New(errs.AssetBadMeta, "another process holds the asset index, slice the sheet there")
}
r := p.byID[id]
if r == nil || r.meta == nil {
return errs.New(errs.AssetNotFound, "the asset is not in the project", log.F("asset", id.String()))
}
m := *r.meta
m.Subs = slices.Clone(subs)
if err := project.WriteAtomic(p.abs(r.path)+MetaSuffix, WriteMeta(&m)); err != nil {
return errs.Wrap(err, errs.VFSIO, "cannot write "+r.path+MetaSuffix).With(log.F("path", r.path))
}
r.meta, r.derived, r.dup, r.key = &m, false, "", ""
p.metas[r.path+MetaSuffix] = true
p.rev++
return nil
}
func (p *Pipeline) SetSettings(id ids.AssetID, s Settings) error {
p.mu.Lock()
defer p.mu.Unlock()
if p.shared {
return errs.New(errs.AssetBadMeta, "another process holds the asset index, change the import settings there")
}
r := p.byID[id]
if r == nil || r.meta == nil {
return errs.New(errs.AssetNotFound, "the asset is not in the project", log.F("asset", id.String()))
}
m := *r.meta
m.Settings = s.Clone()
m.Subs = slices.Clone(r.meta.Subs)
if err := project.WriteAtomic(p.abs(r.path)+MetaSuffix, WriteMeta(&m)); err != nil {
return errs.Wrap(err, errs.VFSIO, "cannot write "+r.path+MetaSuffix).With(log.F("path", r.path))
}
r.meta, r.derived, r.dup, r.key = &m, false, "", ""
p.metas[r.path+MetaSuffix] = true
p.rev++
return nil
}
// ReloadMetadata reconciles a sidecar already atomically saved by the common
// document/file transaction. It never writes the sidecar or invents frame IDs.
func (p *Pipeline) ReloadMetadata(id ids.AssetID) (*Batch, error) {
p.mu.Lock()
defer p.mu.Unlock()
if p.shared {
return nil, errs.New(errs.AssetBadMeta, "another process holds the asset index")
}
r := p.byID[id]
if r == nil || r.meta == nil {
return nil, errs.New(errs.AssetNotFound, "metadata source is not in this project")
}
if err := p.reloadMetadata(r); err != nil {
return nil, err
}
list := []ids.AssetID{id}
list = append(list, p.dependents(id)...)
// CacheSalters include indirect frame dependencies and private channel metadata.
for source, record := range p.byID {
if source != id {
if _, ok := record.importer.(CacheSalter); ok && !slices.Contains(list, source) {
list = append(list, source)
}
}
}
slices.SortFunc(list, func(a, b ids.AssetID) int { return strings.Compare(p.byID[a].path, p.byID[b].path) })
return p.importIDs(list...)
}
func (p *Pipeline) reloadMetadata(r *record) error {
data, err := p.read(r.path + MetaSuffix)
if err != nil {
return err
}
m, err := ParseMeta(data, r.path+MetaSuffix)
if err != nil {
return err
}
if m.ID != r.id {
return errs.New(errs.AssetBadMeta, "saving metadata cannot replace the source AssetID")
}
if m.Importer != "" && m.Importer != r.importer.ID() {
return errs.New(errs.AssetBadMeta, "metadata importer does not match the source")
}
m.Importer = r.importer.ID()
for key, value := range r.importer.Defaults() {
if _, ok := m.Settings[key]; !ok {
m.Settings[key] = value
}
}
seen := map[ids.AssetID]bool{m.ID: true}
for _, sub := range m.Subs {
if sub.ID.IsZero() || seen[sub.ID] {
return errs.New(errs.AssetBadMeta, "frame AssetIDs must be distinct and nonzero")
}
if other, ok := p.pathOf(sub.ID); ok && other != r.path+SubSep+sub.Name {
own := false
for _, old := range r.meta.Subs {
own = own || old.ID == sub.ID
}
if !own {
return errs.New(errs.AssetBadMeta, "frame AssetID belongs to another source")
}
}
seen[sub.ID] = true
}
if bytes.Equal(WriteMeta(r.meta), WriteMeta(m)) {
return nil
}
r.meta, r.key, r.derived = m, "", false
if r.group != "" {
p.groupKey[r.group] = ""
}
p.rev++
return nil
}