package assetmanager import ( "fmt" "os" "path/filepath" "regexp" "slices" "strings" "git.tek.govt.hu/dowerx/opengl-deferred/types/asset" "git.tek.govt.hu/dowerx/opengl-deferred/types/geometry" "git.tek.govt.hu/dowerx/opengl-deferred/types/material" "git.tek.govt.hu/dowerx/opengl-deferred/types/shader" "git.tek.govt.hu/dowerx/opengl-deferred/types/texture" ) type AssetManager struct { assets map[string]asset.Asset } var instance *AssetManager var ( TEXTURE_EXTENSIONS = []string{"png", "tif"} GEOMETRY_EXTENSIONS = []string{"obj"} SHADER_EXTENSIONS = []string{"sdr"} MATERIAL_EXTENSIONS = []string{"mtl"} SCENE_EXTENSIONS = []string{"scn"} VERTEX_REGEX = regexp.MustCompile("vertex_file (?P.*)$") FRAGMENT_REGEX = regexp.MustCompile("fragment_file (?P.*)$") ) func (a *AssetManager) loadItem(path string, itemToLoad os.DirEntry) error { if itemToLoad.Type().IsDir() { items, err := os.ReadDir(filepath.Join(path, itemToLoad.Name())) if err != nil { return err } for _, item := range items { if err = a.loadItem(filepath.Join(path, itemToLoad.Name()), item); err != nil { return err } } } else if itemToLoad.Type().IsRegular() { parts := strings.Split(itemToLoad.Name(), ".") extension := parts[len(parts)-1] var asset asset.Asset var err error if slices.Contains(TEXTURE_EXTENSIONS, extension) { asset, err = texture.Load(filepath.Join(path, itemToLoad.Name())) } else if slices.Contains(GEOMETRY_EXTENSIONS, extension) { asset, err = geometry.LoadOBJ(filepath.Join(path, itemToLoad.Name())) } else if slices.Contains(SHADER_EXTENSIONS, extension) { definition, err := os.ReadFile(filepath.Join(path, itemToLoad.Name())) if err != nil { return err } var vertexPath, fragmentPath string for _, line := range strings.Split(string(definition), "\n") { var matches []string if matches = VERTEX_REGEX.FindStringSubmatch(line); matches != nil { vertexPath = matches[VERTEX_REGEX.SubexpIndex("path")] } else if matches = FRAGMENT_REGEX.FindStringSubmatch(line); matches != nil { fragmentPath = matches[FRAGMENT_REGEX.SubexpIndex("path")] } } asset, err = shader.FromFiles(filepath.Join(path, vertexPath), filepath.Join(path, fragmentPath)) if err != nil { return err } } else if slices.Contains(MATERIAL_EXTENSIONS, extension) { asset, err = material.Load(filepath.Join(path, itemToLoad.Name()), a.assets) } else { return nil } if err != nil { return err } a.assets[filepath.Join(path, itemToLoad.Name()[:len(itemToLoad.Name())-len(extension)-1])] = asset } return nil } func Init(path string) (*AssetManager, error) { if instance != nil { instance.Destroy() } instance = &AssetManager{make(map[string]asset.Asset)} items, err := os.ReadDir(path) if err != nil { return nil, err } for _, item := range items { err = instance.loadItem(path, item) if err != nil { return nil, err } } for k, asset := range instance.assets { material, ok := asset.(material.Material) if ok { material.AttachAssets(instance.assets) instance.assets[k] = material } } fmt.Println("Loaded assets:") for k := range instance.assets { fmt.Printf(" %s\n", k) } return instance, err } func Get() *AssetManager { return instance } func GetAsset[T asset.Asset](a *AssetManager, name string) *T { value, ok := a.assets[name].(T) if !ok { return nil } return &value } func (a *AssetManager) Destroy() { for _, item := range a.assets { item.Delete() } }