6 my %filenamesToProcess;
10 sub collectFileNamesToProcess
12 foreach my $filenameGlob (@_)
14 my @filenames = glob($filenameGlob);
15 foreach my $filename (@filenames)
17 $filenamesToProcess{$filename} = 1;
25 my @sortedFileNames = sort {$a cmp $b} keys %filenamesToProcess;
26 foreach my $filename (@sortedFileNames)
31 print "Total: ", scalar(@sortedFileNames), " files\n";
34 sub iffCallbackCollectSkeletons
37 my $blockname = shift;
40 if ($isChunk && ($blockname eq "SKTI"))
42 while ($iff->getChunkLengthLeft() > 0)
44 my $skeletonTemplateName = $iff->read_string();
45 my $attachmentTransformName = $iff->read_string();
47 # @todo: catch multiple counts of the same skeleton template name.
48 $skeletonNames{$skeletonTemplateName} = 1;
58 my $satFileName = shift;
61 # Collect skeleton templates referenced by this iff.
63 $iff->walkIff(\
&iffCallbackCollectSkeletons
);
65 # Process skeleton template names.
66 my $faceSkeletonCount = 0;
68 foreach my $skeletonTemplateName (sort {$a cmp $b} keys %skeletonNames)
70 my $workingSkeletonName = $skeletonTemplateName;
72 # Strip off directories in the skeleton template name.
73 $workingSkeletonName =~ s!\\!/!;
74 $workingSkeletonName =~ s!^.+/!!;
76 # Strip off .skt part.
77 $workingSkeletonName =~ s!.skt$!!;
78 print "workingSkeletonName=[$workingSkeletonName]\n" if $debug;
80 if ($workingSkeletonName eq "all_b")
82 #ignore all_b skeleton.
84 elsif ($workingSkeletonName =~ m/([^_]+)_([^_]+)_face/)
88 my $speciesAbbrev = $1;
89 my $genderAbbrev = $2;
91 my $invalidSatName = 0;
93 my $shouldContainForSpecies = '(^|_)' . $speciesAbbrev . '_';
94 if (!($satFileName =~ m/$shouldContainForSpecies/))
99 my $satShouldContainForGender = '_' . $genderAbbrev . '(_|.sat)';
100 if (!($satFileName =~ m/$satShouldContainForGender/))
105 if ($invalidSatName > 0)
107 # The SAT file references species/gender specific skeleton template but the SAT filename doesn't indicate the species/gender dependency.\n";
108 print "$satFileName\t$skeletonTemplateName\tspecies/gender skeleton referenced, invalid SAT name.\n";
113 # Try matching the whole working skeleton name within the sat, indicating that the skeleton and sat are joined.
114 my $validSatNamePattern = '(^|_)' . $workingSkeletonName . '(_|.sat)';
115 if (!($satFileName =~ m/$validSatNamePattern/))
117 print "$satFileName\t$skeletonTemplateName\tunexpected skeleton template name\n";
122 print "$satFileName\t****\treferenced $faceSkeletonCount face skeletons\n" if $faceSkeletonCount > 1;
127 foreach my $filename (@_)
129 # Open the file, create an Iff instance from it.
131 open($fileHandle, "<$filename") or die "cannot open file [$filename]: $!";
133 my $iff = Iff
->createFromFileHandle($fileHandle);
137 # Handle Iff contents.
138 my $initialName = $iff->getCurrentName();
139 if (($initialName ne "SMAT") || !$iff->isCurrentForm())
141 print "$filename: not a .SAT file, ignoring\n";
146 processSatIff
($filename, $iff);
154 die "Usage: perl findBadSkeletonBindings.pl <.sat fileglob> [ <.sat fileglob> [...]]\n" if (@ARGV == 0);
156 # Collect files to process.
157 collectFileNamesToProcess
(@ARGV);
158 printFileNames
() if $debug;
159 processFiles
(sort {$a cmp $b} keys %filenamesToProcess);