package descriptors import ( "encoding/json" "fmt" "strings" components "github.com/DegustatorPonos/RuinesOfRafdolon/Components" coreobjects "github.com/DegustatorPonos/RuinesOfRafdolon/CoreObjects" rl "github.com/gen2brain/raylib-go/raylib" ) const ObjectsDirName string = "Objects" type ObjectDescriptor struct { Name string YLevelOffset float64 Textures []*ObjectTextureBlock Colliders []*ObjectColliderBlock } // Maps objects by their IDs func MapObjectDescriptors(loaded []*ObjectDescriptor) map[string]*ObjectDescriptor { var outp = make(map[string]*ObjectDescriptor, 0) for _, v := range loaded { outp[v.Name] = v } return outp } func (base *ObjectDescriptor) IsValid() error { if base.Textures == nil { return fmt.Errorf("The textures are not specified") } for i, v := range base.Textures { // The texture was not specified if v.TextureId == nil && len(v.Name) == 0 { return fmt.Errorf("The texture #%d was not specified (neither texture name nor ID)", i) } } return nil } func (base *ObjectDescriptor) parseTextures() []*coreobjects.TextureBlock { var outp = make([]*coreobjects.TextureBlock, 0, len(base.Textures)) for _, v := range base.Textures { var texture, err = v.GetTexture() if err != nil { rl.TraceLog(rl.LogWarning, "Failed to get the required by the object %s texture: %s", base.Name, err.Error()) continue } outp = append(outp, &coreobjects.TextureBlock { Texture: texture, Window: v.getTargetWindow(texture), }) } return outp } func (base *ObjectDescriptor) parseColliders() []*coreobjects.ColliderBlock { var outp = make([]*coreobjects.ColliderBlock, 0, len(base.Colliders)) for _, v := range base.Colliders { var parsed, err = v.GetCollider() if err != nil { rl.TraceLog(rl.LogWarning, "Failed to parse the required by the object %s collidet: %s", base.Name, err.Error()) continue } outp = append(outp, &coreobjects.ColliderBlock{ Collider: parsed, Offset: v.Offset, }) } return outp } func (base *ObjectDescriptor) Parse() coreobjects.DynamicObject { return coreobjects.DynamicObject { YLevelOffset: float32(base.YLevelOffset), Textures: base.parseTextures(), Colliders: base.parseColliders(), } } type ObjectTextureBlock struct { Name string TextureId *uint64 Offset rl.Vector2 TargetScale *rl.Vector2 } func (base *ObjectTextureBlock) GetTexture() (*rl.Texture2D, error) { if base.TextureId != nil { return components.Resources.Textures.GetTexture(*base.TextureId) } return components.Resources.Textures.GetTextureByName(base.Name) } // Calculates the target window of the tetxure block. Should be provided with its target texture func (base *ObjectTextureBlock) getTargetWindow(texture *rl.Texture2D) *rl.Rectangle { var outp = &rl.Rectangle { X: base.Offset.X, Y: base.Offset.Y, Width: float32(texture.Width), Height: float32(texture.Height), } if base.TargetScale != nil { outp.Width = base.TargetScale.X outp.Height = base.TargetScale.Y } return outp } type ObjectColliderBlock struct { Type string Size rl.Vector2 Offset rl.Vector2 } func (base *ObjectColliderBlock) GetCollider() (coreobjects.Collider, error) { switch strings.ToLower(base.Type) { case "box": return base.parseAsBox(), nil } return nil, fmt.Errorf("Failed to parse collider: type %s is unknown", base.Type) } func (base *ObjectColliderBlock) parseAsBox() coreobjects.Collider { var outp = (&coreobjects.BoxCollider{}).Init( base.Offset.X, base.Offset.Y, base.Size.X, base.Size.Y ) return outp } func (base *ObjectDescriptor) String() string { var outp, jsonErr = json.Marshal(base) if jsonErr != nil { return fmt.Sprintf("Failed to parse object: %s", jsonErr.Error()) } return string(outp) }