initial checkin from nexuiz svn r8756
[xonotic/xonotic.git] / misc / tools / dependencies.pl
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 my %files = ();
7 my %shaders = ();
8
9 sub ReadShaders()
10 {
11         for my $sf(<scripts/*.shader>)
12         {
13                 my $curshader = undef;
14                 my @tex = ();
15                 my $level = 0;
16                 open my $fh, "<", $sf
17                         or die "<$sf: $!";
18                 while(<$fh>)
19                 {
20                         s/\r//gs;
21                         chomp;
22
23                         s/\/\/.*//s;
24                         s/^\s+//;
25                         s/\s+$//;
26                         next if /^$/;
27
28                         my @line = map { s/"//g; $_; } split /\s+/, $_;
29
30                         if($line[0] eq '{')
31                         {
32                                 ++$level;
33                         }
34                         elsif($line[0] eq '}')
35                         {
36                                 --$level;
37                                 if($level <= 0)
38                                 {
39                                         $level = 0;
40                                         if(defined $curshader)
41                                         {
42                                                 $shaders{lc $curshader} = { shaderfile => $sf, textures => [ @tex ] };
43                                         }
44                                         $curshader = undef;
45                                 }
46                         }
47                         elsif($level == 0)
48                         {
49                                 $curshader = $line[0];
50                                 @tex = ();
51                         }
52                         elsif($level == 1 and lc $line[0] eq 'qer_editorimage')
53                         {
54                                 push @tex, $line[1];
55                         }
56                         elsif($level == 1 and lc $line[0] eq 'qer_lightimage')
57                         {
58                                 push @tex, $line[1];
59                         }
60                         elsif($level == 1 and lc $line[0] eq 'skyparms')
61                         {
62                                 for(qw/rt lf ft bk up dn/)
63                                 {
64                                         push @tex, "$line[1]_$_";
65                                         push @tex, "$line[3]_$_";
66                                 }
67                         }
68                         elsif($level == 2 and lc $line[0] eq 'map')
69                         {
70                                 push @tex, $line[1];
71                         }
72                         elsif($level == 2 and lc $line[0] eq 'animmap')
73                         {
74                                 for(2..(@line - 1))
75                                 {
76                                         push @tex, $line[$_];
77                                 }
78                         }
79                 }
80         }
81 }
82
83 sub AddFile($)
84 {
85         my ($file) = @_;
86         return 0
87                 unless -e $file;
88         ++$files{$file};
89         return 1;
90 }
91
92 sub AddSound($)
93 {
94         my ($tex) = @_;
95         $tex =~ s/\.ogg$|\.wav$//i;
96         AddFile "$tex.ogg" or
97         AddFile "$tex.wav" or
98         AddFile "sound/$tex.ogg" or
99         AddFile "sound/$tex.wav";
100 }
101
102 sub AddTexture($)
103 {
104         my ($tex) = @_;
105         $tex =~ s/\.jpg$|\.tga$|\.png$//i;
106         AddFile "$tex.jpg" or
107         AddFile "$tex.tga" or
108         AddFile "$tex.png"
109                 or return 0;
110         for('_shirt', '_pants', '_glow', '_norm', '_bump', '_gloss')
111         {
112                 AddFile "$tex$_.jpg" or
113                 AddFile "$tex$_.tga" or
114                 AddFile "$tex$_.png";
115         }
116         return 1;
117 }
118
119 sub AddShader($)
120 {
121         my ($shader) = @_;
122         $shader =~ s/\.jpg$|\.tga$|\.png$//i;
123         my $si = $shaders{lc $shader};
124         if(not defined $si)
125         {
126                 AddTexture $shader
127                         or warn "Unknown shader used: $shader";
128         }
129         else
130         {
131                 AddFile $si->{shaderfile};
132                 AddTexture $_
133                         for @{$si->{textures}};
134         }
135 }
136
137 sub AddMapDependencies($)
138 {
139         my ($data) = @_;
140         for(/^"noise.*" "(.*)"/gm)
141         {
142                 AddSound $1;
143         }
144         for(/^"sound.*" "(.*)"/gm)
145         {
146                 AddSound $1;
147         }
148         for(/^"music" "(.*)"/gm)
149         {
150                 AddSound $1;
151         }
152         for(/^"model" "(.*)"/gm)
153         {
154                 # TODO make this AddModel
155                 # TODO and find the shaders the model uses
156                 AddFile $1;
157         }
158         for(/^"lodmodel.*" "(.*)"/gm)
159         {
160                 AddFile $1;
161         }
162 }
163
164 sub AddMapinfoDependencies($)
165 {
166         my ($data) = @_;
167         for($data =~ /^cdtrack (.*)$/gm)
168         {
169                 AddSound "sound/cdtracks/$1";
170         }
171 }
172
173 sub AddCfgDependencies($)
174 {
175         my ($data) = @_;
176         for($data =~ /^cd loop "?(.*?)"?$/gm)
177         {
178                 AddSound "sound/cdtracks/$1";
179         }
180 }
181
182 sub AddShaderDependencies($)
183 {
184         my ($data) = @_;
185
186         my $n = length($data) / 72;
187         for(0..($n-1))
188         {
189                 my $s = substr $data, $_ * 72, 64;
190                 $s =~ s/\0.*$//s;
191                 AddShader $s;
192         }
193 }
194
195 sub AddFaceDependencies($$)
196 {
197         my ($base, $data) = @_;
198
199         my $n = length($data) / 104;
200         for(0..($n-1))
201         {
202                 my $l = unpack "V", substr $data, $_ * 104 + 28, 4;
203                 AddTexture sprintf "maps/%s/lm_%04d", $base, $l;
204                 AddTexture sprintf "maps/%s/lm_%04d", $base, $l | 1; # deluxe
205         }
206 }
207
208
209 ReadShaders();
210
211 for(<maps/*.ent>)
212 {
213         AddFile $_;
214
215         my $data = do {
216                 undef local $/;
217                 open my $fh, "<", $_
218                         or die "<$_: $!";
219                 <$fh>;
220         };
221         AddMapDependencies $data;
222 }
223
224 for(<maps/*.bsp>)
225 {
226         AddFile $_;
227
228         m!^maps/(.*)\.bsp! or die "perl is stupid";
229         my $b = $1;
230         AddFile "maps/$b.mapinfo";
231         AddFile "maps/$b.jpg";
232         AddFile "maps/$b.cfg";
233         AddFile "maps/$b.waypoints";
234         AddFile "maps/$b.rtlights";
235         AddTexture "gfx/$b\_radar.tga";
236         AddTexture "gfx/$b\_mini.tga";
237
238         my $data = do {
239                 undef local $/;
240                 open my $fh, "<", "maps/$b.mapinfo"
241                         or warn "<maps/$b.mapinfo: $!";
242                 <$fh>;
243         };
244         AddMapinfoDependencies $data;
245
246         $data = do {
247                 undef local $/;
248                 open my $fh, "<", "maps/$b.cfg"
249                         or warn "<maps/$b.cfg: $!";
250                 <$fh>;
251         };
252         AddCfgDependencies $data;
253
254         $data = do {
255                 undef local $/;
256                 open my $fh, "-|", 'bsptool.pl', $_, '-xentities'
257                         or die "<$_: $!";
258                 <$fh>;
259         };
260         AddMapDependencies $data;
261
262         $data = do {
263                 undef local $/;
264                 open my $fh, "-|", 'bsptool.pl', $_, '-xfaces'
265                         or die "<$_: $!";
266                 <$fh>;
267         };
268         AddFaceDependencies $b, $data;
269
270         $data = do {
271                 undef local $/;
272                 open my $fh, "-|", 'bsptool.pl', $_, '-xtextures'
273                         or die "<$_: $!";
274                 <$fh>;
275         };
276         AddShaderDependencies $data;
277 }
278
279 sub RecurseDir($);
280 sub RecurseDir($)
281 {
282         my ($dir) = @_;
283         if(-d $dir)
284         {
285                 for(<$dir/*>)
286                 {
287                         RecurseDir $_;
288                 }
289         }
290         else
291         {
292                 warn "Unused file: $dir"
293                         unless $files{$dir};
294         }
295 }
296
297 for(<*>)
298 {
299         RecurseDir $_;
300 }
301
302 print "$_\0"
303         for sort keys %files;