@@ -1969,15 +1969,6 @@ func SetAnim(obj interface{}, fVal, structVal, parent reflect.Value, sffOverride
19691969 anim = int32 (fv .Int ())
19701970 }
19711971 if fv , ok := get ("Spr" ); ok && fv .Kind () == reflect .Array && fv .Len () == 2 {
1972- if warnMissing {
1973- if _ , sf , ok := findFieldByINITag (structVal , "spr" ); ok &&
1974- strings .EqualFold (strings .TrimSpace (sf .Tag .Get ("warn" )), "false" ) {
1975- warnMissing = false
1976- } else if _ , sf , ok := findFieldByINITag (parent , "spr" ); ok &&
1977- strings .EqualFold (strings .TrimSpace (sf .Tag .Get ("warn" )), "false" ) {
1978- warnMissing = false
1979- }
1980- }
19811972 spr [0 ] = int32 (fv .Index (0 ).Int ())
19821973 spr [1 ] = int32 (fv .Index (1 ).Int ())
19831974 hasSpr = true
@@ -2610,9 +2601,13 @@ func PopulateDataPointers(obj interface{}, rootLocalcoord [2]int32) {
26102601 rootSff = s
26112602 }
26122603 }
2604+ var inheritedKeys map [string ]bool
2605+ if m , ok := obj .(* Motif ); ok {
2606+ inheritedKeys = m .inheritedKeys
2607+ }
26132608
26142609 // Thread both localcoord and effective SFF through recursion.
2615- var populate func (v reflect.Value , parent reflect.Value , currentLocalCoord [2 ]int32 , currentSff * Sff , skipInit bool , warnMissing bool )
2610+ var populate func (v reflect.Value , parent reflect.Value , currentLocalCoord [2 ]int32 , currentSff * Sff , skipInit bool , warnMissing bool , path string )
26162611
26172612 // Types we look for
26182613 animPtrType := reflect .TypeOf ((* Anim )(nil ))
@@ -2622,15 +2617,15 @@ func PopulateDataPointers(obj interface{}, rootLocalcoord [2]int32) {
26222617 fadePtrType := reflect .TypeOf ((* Fade )(nil ))
26232618
26242619 // The recursive function
2625- populate = func (v reflect.Value , parent reflect.Value , currentLocalCoord [2 ]int32 , currentSff * Sff , skipInit bool , warnMissing bool ) {
2620+ populate = func (v reflect.Value , parent reflect.Value , currentLocalCoord [2 ]int32 , currentSff * Sff , skipInit bool , warnMissing bool , path string ) {
26262621 if ! v .IsValid () {
26272622 return
26282623 }
26292624 if v .Kind () == reflect .Ptr {
26302625 if v .IsNil () {
26312626 return
26322627 }
2633- populate (v .Elem (), parent , currentLocalCoord , currentSff , skipInit , warnMissing )
2628+ populate (v .Elem (), parent , currentLocalCoord , currentSff , skipInit , warnMissing , path )
26342629 return
26352630 }
26362631
@@ -2643,6 +2638,17 @@ func PopulateDataPointers(obj interface{}, rootLocalcoord [2]int32) {
26432638 // Effective SFF for this struct (may be overridden by the field tag of children)
26442639 effectiveSffForThisStruct := currentSff
26452640
2641+ joinPath := func (base , elem string ) string {
2642+ elem = strings .ToLower (strings .ReplaceAll (strings .TrimSpace (elem ), " " , "_" ))
2643+ if elem == "" {
2644+ return base
2645+ }
2646+ if base == "" {
2647+ return elem
2648+ }
2649+ return base + "." + elem
2650+ }
2651+
26462652 for i := 0 ; i < v .NumField (); i ++ {
26472653 fVal := v .Field (i )
26482654 fType := t .Field (i )
@@ -2672,27 +2678,33 @@ func PopulateDataPointers(obj interface{}, rootLocalcoord [2]int32) {
26722678 }
26732679 }
26742680
2681+ fieldPath := path
2682+ if tag := strings .TrimSpace (fType .Tag .Get ("ini" )); tag != "" &&
2683+ ! strings .HasPrefix (strings .ToLower (tag ), "map:" ) {
2684+ fieldPath = joinPath (path , tag )
2685+ }
2686+
26752687 // Check for skipInit tag on this field
26762688 childSkipInit := skipInit
26772689 if fType .Tag .Get ("skipinit" ) == "true" {
26782690 childSkipInit = true
26792691 }
26802692 childWarnMissing := warnMissing
2681- if strings . EqualFold ( strings . TrimSpace ( fType . Tag . Get ( "warn" )), "false" ) {
2693+ if inheritedKeys != nil && fieldPath != "" && ( inheritedKeys [ fieldPath + ".anim" ] || inheritedKeys [ fieldPath + ".spr" ] ) {
26822694 childWarnMissing = false
26832695 }
26842696
26852697 kind := fVal .Kind ()
26862698
26872699 // Recurse for struct or non-nil ptr
26882700 if kind == reflect .Struct || (kind == reflect .Ptr && ! fVal .IsNil ()) {
2689- populate (fVal , v , localCoordForThisStruct , nextSff , childSkipInit , childWarnMissing )
2701+ populate (fVal , v , localCoordForThisStruct , nextSff , childSkipInit , childWarnMissing , fieldPath )
26902702 continue
26912703 }
26922704 // If it's a map, recurse as well
26932705 if kind == reflect .Map {
26942706 // Pass along the possibly overridden SFF from this field's tag.
2695- populate (fVal , parent , localCoordForThisStruct , nextSff , childSkipInit , childWarnMissing )
2707+ populate (fVal , parent , localCoordForThisStruct , nextSff , childSkipInit , childWarnMissing , fieldPath )
26962708 continue
26972709 }
26982710 // If it's *Anim
@@ -2743,12 +2755,19 @@ func PopulateDataPointers(obj interface{}, rootLocalcoord [2]int32) {
27432755 // If we have a slice or array, recurse into each element
27442756 case reflect .Slice , reflect .Array :
27452757 for i := 0 ; i < v .Len (); i ++ {
2746- populate (v .Index (i ), parent , currentLocalCoord , currentSff , skipInit , warnMissing )
2758+ populate (v .Index (i ), parent , currentLocalCoord , currentSff , skipInit , warnMissing , path )
27472759 }
27482760 case reflect .Map :
27492761 for _ , key := range v .MapKeys () {
27502762 val := v .MapIndex (key )
2751- populate (val , parent , currentLocalCoord , currentSff , skipInit , warnMissing )
2763+ childPath := path
2764+ if key .Kind () == reflect .String {
2765+ k := strings .ToLower (strings .ReplaceAll (strings .TrimSpace (key .String ()), " " , "_" ))
2766+ if k != "" {
2767+ childPath = k
2768+ }
2769+ }
2770+ populate (val , parent , currentLocalCoord , currentSff , skipInit , warnMissing , childPath )
27522771 }
27532772 default :
27542773 // basic types: do nothing
@@ -2761,7 +2780,7 @@ func PopulateDataPointers(obj interface{}, rootLocalcoord [2]int32) {
27612780 return
27622781 }
27632782 // Start recursion with the original user-supplied localcoord
2764- populate (v .Elem (), v .Elem (), rootLocalcoord , rootSff , false , true )
2783+ populate (v .Elem (), v .Elem (), rootLocalcoord , rootSff , false , true , "" )
27652784}
27662785
27672786// Split a [Music] key into (prefix, property) while allowing dots in prefix.
0 commit comments