176 lines
4.8 KiB
Go
176 lines
4.8 KiB
Go
package assets
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"gitea.boner.be/bdnugget/goonscape/logging"
|
|
"gitea.boner.be/bdnugget/goonscape/types"
|
|
rl "github.com/gen2brain/raylib-go/raylib"
|
|
)
|
|
|
|
var (
|
|
assetMutex sync.RWMutex
|
|
loadedModels map[string]types.ModelAsset
|
|
audioMutex sync.Mutex
|
|
audioInitialized bool
|
|
)
|
|
|
|
func init() {
|
|
loadedModels = make(map[string]types.ModelAsset)
|
|
}
|
|
|
|
// Helper function to load animations for a model
|
|
func loadModelAnimations(animPaths map[string]string) (types.AnimationSet, error) {
|
|
var animSet types.AnimationSet
|
|
|
|
// Load idle animations if specified
|
|
if idlePath, ok := animPaths["idle"]; ok {
|
|
idleAnims := rl.LoadModelAnimations(idlePath)
|
|
if len(idleAnims) > 0 {
|
|
animSet.Idle = idleAnims
|
|
rl.TraceLog(rl.LogInfo, "Loaded idle animation: %s (%d frames, %f seconds)",
|
|
idlePath, idleAnims[0].FrameCount, float32(idleAnims[0].FrameCount)/60.0)
|
|
}
|
|
}
|
|
|
|
// Load walk animations if specified
|
|
if walkPath, ok := animPaths["walk"]; ok {
|
|
walkAnims := rl.LoadModelAnimations(walkPath)
|
|
if len(walkAnims) > 0 {
|
|
animSet.Walk = walkAnims
|
|
rl.TraceLog(rl.LogInfo, "Loaded walk animation: %s (%d frames, %f seconds)",
|
|
walkPath, walkAnims[0].FrameCount, float32(walkAnims[0].FrameCount)/60.0)
|
|
}
|
|
}
|
|
|
|
return animSet, nil
|
|
}
|
|
|
|
func LoadModels() ([]types.ModelAsset, error) {
|
|
logging.Info.Println("Loading models")
|
|
assetMutex.Lock()
|
|
defer assetMutex.Unlock()
|
|
|
|
if len(loadedModels) > 0 {
|
|
logging.Info.Println("Returning cached models")
|
|
models := make([]types.ModelAsset, 0, len(loadedModels))
|
|
for _, model := range loadedModels {
|
|
models = append(models, model)
|
|
}
|
|
return models, nil
|
|
}
|
|
|
|
// Goonion model and animations
|
|
goonerModel := rl.LoadModel("resources/models/gooner/walk_no_y_transform.glb")
|
|
goonerAnims, err := loadModelAnimations(map[string]string{
|
|
"idle": "resources/models/gooner/idle_no_y_transform.glb",
|
|
"walk": "resources/models/gooner/walk_no_y_transform.glb",
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Apply transformations
|
|
transform := rl.MatrixIdentity()
|
|
transform = rl.MatrixMultiply(transform, rl.MatrixRotateY(180*rl.Deg2rad))
|
|
transform = rl.MatrixMultiply(transform, rl.MatrixRotateX(-90*rl.Deg2rad))
|
|
transform = rl.MatrixMultiply(transform, rl.MatrixScale(1.0, 1.0, 1.0))
|
|
goonerModel.Transform = transform
|
|
|
|
// Coomer model (ready for animations)
|
|
coomerModel := rl.LoadModel("resources/models/coomer/idle_notransy.glb")
|
|
coomerAnims, err := loadModelAnimations(map[string]string{
|
|
"idle": "resources/models/coomer/idle_notransy.glb",
|
|
"walk": "resources/models/coomer/unsteadywalk_notransy.glb",
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
coomerModel.Transform = transform
|
|
|
|
// Shreke model (ready for animations)
|
|
shrekeModel := rl.LoadModel("resources/models/shreke/Animation_Slow_Orc_Walk_withSkin.glb")
|
|
shrekeAnims, err := loadModelAnimations(map[string]string{
|
|
"idle": "resources/models/shreke/Animation_Slow_Orc_Walk_withSkin.glb",
|
|
"walk": "resources/models/shreke/Animation_Excited_Walk_M_withSkin.glb",
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
shrekeModel.Transform = transform
|
|
|
|
// Store loaded models
|
|
models := []types.ModelAsset{
|
|
{
|
|
Name: "gooner",
|
|
Model: goonerModel,
|
|
Animation: append(goonerAnims.Idle, goonerAnims.Walk...),
|
|
AnimFrames: int32(len(goonerAnims.Idle) + len(goonerAnims.Walk)),
|
|
Animations: goonerAnims,
|
|
YOffset: 0.0,
|
|
},
|
|
{
|
|
Model: coomerModel,
|
|
Animation: append(coomerAnims.Idle, coomerAnims.Walk...),
|
|
AnimFrames: int32(len(coomerAnims.Idle) + len(coomerAnims.Walk)),
|
|
Animations: coomerAnims,
|
|
YOffset: -4.0,
|
|
},
|
|
{
|
|
Model: shrekeModel,
|
|
Animation: append(shrekeAnims.Idle, shrekeAnims.Walk...),
|
|
AnimFrames: int32(len(shrekeAnims.Idle) + len(shrekeAnims.Walk)),
|
|
Animations: shrekeAnims,
|
|
YOffset: 0.0,
|
|
},
|
|
}
|
|
|
|
for _, model := range models {
|
|
loadedModels[model.Name] = model
|
|
}
|
|
|
|
return models, nil
|
|
}
|
|
|
|
func LoadMusic(filename string) (rl.Music, error) {
|
|
logging.Info.Printf("Loading music from %s", filename)
|
|
audioMutex.Lock()
|
|
defer audioMutex.Unlock()
|
|
|
|
if !rl.IsAudioDeviceReady() {
|
|
err := fmt.Errorf("audio device not initialized")
|
|
logging.Error.Println(err)
|
|
return rl.Music{}, err
|
|
}
|
|
|
|
music := rl.LoadMusicStream(filename)
|
|
if music.CtxType == 0 {
|
|
err := fmt.Errorf("failed to load music stream")
|
|
logging.Error.Println(err)
|
|
return rl.Music{}, err
|
|
}
|
|
logging.Info.Println("Music loaded successfully")
|
|
return music, nil
|
|
}
|
|
|
|
func UnloadModels(models []types.ModelAsset) {
|
|
assetMutex.Lock()
|
|
defer assetMutex.Unlock()
|
|
|
|
for _, model := range models {
|
|
if model.Animation != nil {
|
|
for i := int32(0); i < model.AnimFrames; i++ {
|
|
rl.UnloadModelAnimation(model.Animation[i])
|
|
}
|
|
}
|
|
rl.UnloadModel(model.Model)
|
|
rl.UnloadTexture(model.Texture)
|
|
delete(loadedModels, model.Name)
|
|
}
|
|
}
|
|
|
|
func UnloadMusic(music rl.Music) {
|
|
rl.UnloadMusicStream(music)
|
|
}
|