update readme and add gitignore
[client-tools.git] / tools / findBadSkeletonBindings.pl
blobbe523619c7cf63f93e9757d14a0d91f576a93f69
1 #!/bin/perl
2 use strict;
4 use Iff;
6 my %filenamesToProcess;
7 my $debug = 0;
8 my %skeletonNames;
10 sub collectFileNamesToProcess
12 foreach my $filenameGlob (@_)
14 my @filenames = glob($filenameGlob);
15 foreach my $filename (@filenames)
17 $filenamesToProcess{$filename} = 1;
22 sub printFileNames
24 print "Filenames:\n";
25 my @sortedFileNames = sort {$a cmp $b} keys %filenamesToProcess;
26 foreach my $filename (@sortedFileNames)
28 print "$filename\n";
31 print "Total: ", scalar(@sortedFileNames), " files\n";
34 sub iffCallbackCollectSkeletons
36 my $iff = shift;
37 my $blockname = shift;
38 my $isChunk = 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;
52 return 1;
55 sub processSatIff
57 # Setup args.
58 my $satFileName = shift;
59 my $iff = shift;
61 # Collect skeleton templates referenced by this iff.
62 %skeletonNames = ();
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/)
86 ++$faceSkeletonCount;
88 my $speciesAbbrev = $1;
89 my $genderAbbrev = $2;
91 my $invalidSatName = 0;
93 my $shouldContainForSpecies = '(^|_)' . $speciesAbbrev . '_';
94 if (!($satFileName =~ m/$shouldContainForSpecies/))
96 ++$invalidSatName;
99 my $satShouldContainForGender = '_' . $genderAbbrev . '(_|.sat)';
100 if (!($satFileName =~ m/$satShouldContainForGender/))
102 ++$invalidSatName;
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";
111 else
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;
125 sub processFiles
127 foreach my $filename (@_)
129 # Open the file, create an Iff instance from it.
130 my $fileHandle;
131 open($fileHandle, "<$filename") or die "cannot open file [$filename]: $!";
133 my $iff = Iff->createFromFileHandle($fileHandle);
135 close($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";
143 else
145 $iff->enterForm();
146 processSatIff($filename, $iff);
147 $iff->exitForm();
153 # Print usage.
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);