]> icculus.org git repositories - divverent/nexuiz.git/blob - misc/tools/nexuiz-map-compiler
allow a .map or .bsp suffix in the command line
[divverent/nexuiz.git] / misc / tools / nexuiz-map-compiler
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use POSIX;
6 use File::Temp;
7
8 # change these to match your system, or define them in ~/.nexuiz-map-compiler
9 # (just copy paste this part to the file ~/.nexuiz-map-compiler)
10
11         # Path to Nexuiz (where the data directory is in)
12         our $NEXUIZDIR   = '/home/polzer/Nexvn/nexuiz';
13
14         # Path to your q3map2 program. You find it in your GtkRadiant/install
15         # directory.
16         our $Q3MAP2      = '/home/users4/ommz/polzer/bin/q3map2.x86';
17
18         # General flags for q3map2 (for example -threads 4)
19         our $Q3MAP2FLAGS = '';
20
21         # Default flags for the -bsp stage
22         our $BSPFLAGS    = '-samplesize 8 -minsamplesize 4 -mv 1000000 -mi 6000000';
23
24         # Default flags for the -vis stage
25         our $VISFLAGS    = '';
26
27         # Default flags for the -light stage
28         our $LIGHTFLAGS  = '-deluxe -patchshadows -samples 3 -lightmapsize 512 -bounce 8 -fastbounce -bouncegrid';
29
30 # end of user changable part
31
32 do "$ENV{HOME}/.nexuiz-map-compiler";
33
34 sub Usage()
35 {
36         print <<EOF;
37 Usage:
38 $0 mapname [-bsp bspflags...] [-vis visflags...] [-light lightflags...]
39 EOF
40         exit 1;
41 }
42
43 my $options =
44 {
45         bsp => [split /\s+/, $BSPFLAGS],
46         vis => [split /\s+/, $VISFLAGS],
47         light => [split /\s+/, $LIGHTFLAGS],
48         maps => [],
49         scale => 1
50 };
51
52 my $curmode = 'maps';
53
54 while(@ARGV)
55 {
56         $_ = shift @ARGV;
57         my $enterflags = undef;
58         if($_ eq '-bsp' or $_ eq '-meta')
59         {
60                 $enterflags = 'bsp';
61         }
62         elsif($_ eq '-vis')
63         {
64                 $enterflags = 'vis';
65         }
66         elsif($_ eq '-light')
67         {
68                 $enterflags = 'light';
69         }
70         elsif($_ eq '-map')
71         {
72                 $curmode = 'maps';
73         }
74         elsif($_ eq '-scale')
75         {
76                 $options->{scale} = (shift @ARGV) || 1;
77         }
78         elsif($_ eq '-novis')
79         {
80                 $options->{vis} = undef;
81         }
82         elsif($_ eq '-nolight')
83         {
84                 $options->{light} = undef;
85         }
86         elsif($_ =~ /^-(-.*)/)
87         {
88                 if($curmode eq 'maps')
89                 {
90                         $curmode = 'bsp';
91                 }
92                 push @{$options->{$curmode}}, $1;
93         }
94         elsif($_ =~ /^-/ and $curmode eq 'maps')
95         {
96                 $curmode = 'bsp';
97                 push @{$options->{$curmode}}, $_;
98         }
99         else
100         {
101                 push @{$options->{$curmode}}, $_;
102         }
103         if(defined $enterflags)
104         {
105                 $curmode = $enterflags;
106                 if($ARGV[0] eq '+')
107                 {
108                         shift @ARGV;
109                 }
110                 else
111                 {
112                         $options->{$curmode} = [];
113                 }
114         }
115 }
116
117 my $linkdir = File::Temp::tempdir("nexuiz-map-compiler.XXXXXX", TMPDIR => 1, CLEANUP => 1);
118
119 sub q3map2(@)
120 {
121         my @args = ($Q3MAP2, split(/\s+/, $Q3MAP2FLAGS), '-game', 'nexuiz', '-fs_basepath', $NEXUIZDIR, '-fs_basepath', $linkdir, '-v', @_);
122         print "\$ @args\n";
123         return !system @args;
124 }
125
126 (my $mapdir = getcwd()) =~ s!/[^/]*(?:$)!!;
127 $mapdir = "/" if $mapdir eq "";
128 symlink "$mapdir", "$linkdir/data";
129
130 my ($prescale, $postscale) = ($options->{scale} =~ /^([0-9.]+)(?::([0-9.]+))?$/);
131 $postscale = 1 if not defined $postscale;
132
133 for my $m(@{$options->{maps}})
134 {
135         $m =~ s/\.(?:map|bsp)$//;
136         if($prescale != 1 or $postscale != 1)
137         {
138                 open my $checkfh, "<", "$m.map"
139                         or die "open $m.map: $!";
140                 my $keeplights = 0;
141                 while(<$checkfh>)
142                 {
143                         /^\s*"_keeplights"\s+"1"\s*$/
144                                 or next;
145                         $keeplights = 1;
146                 }
147                 close $checkfh;
148                 die "$m does not define _keeplights to 1"
149                         unless $keeplights;
150         }
151
152         my %shaders = map { m!/([^/.]*)\.shader(?:$)! ? ($1 => 1) : () } glob "../scripts/*.shader";
153
154         my $previous_shaderlist = undef;
155         my $shaderlist = "";
156         if(open my $fh, "<", "$NEXUIZDIR/scripts/shaderlist.txt")
157         {
158                 while(<$fh>)
159                 {
160                         $shaderlist .= $_;
161                 }
162
163                 # we may have to restore the file on exit
164                 $previous_shaderlist = $shaderlist
165                         if "$NEXUIZDIR/data" eq $mapdir;
166         }
167         else
168         {
169                 # possibly extract the shader list from a pk3?
170                 local $ENV{N} = $NEXUIZDIR;
171                 $shaderlist = `cd "\$N" && for X in "\$N"/data/data*.pk3; do Y=\$X; done; unzip -p "\$Y" scripts/shaderlist.txt`;
172         }
173
174         my $shaderlist_new = "";
175         for(split /\r?\n|\r/, $shaderlist)
176         {
177                 delete $shaders{$_};
178                 $shaderlist_new .= "$_\n";
179         }
180         if(%shaders)
181         {
182                 for(sort keys %shaders)
183                 {
184                         $shaderlist_new .= "$_\n";
185                 }
186         }
187         else
188         {
189                 $shaderlist_new = undef;
190         }
191
192         my $restore_shaderlist = sub
193         {
194                 if(defined $shaderlist_new)
195                 {
196                         if(defined $previous_shaderlist)
197                         {
198                                 open my $fh, ">", "$mapdir/scripts/shaderlist.txt";
199                                 print $fh $previous_shaderlist;
200                                 close $fh;
201                         }
202                         else
203                         {
204                                 unlink "$mapdir/scripts/shaderlist.txt";
205                         }
206                 }
207         };
208         local $SIG{INT} = sub
209         {
210                 print "SIGINT caught, cleaning up...\n";
211                 $restore_shaderlist->();
212                 exit 0;
213         };
214
215         eval
216         {
217                 if(defined $shaderlist_new)
218                 {
219                         mkdir "$mapdir/scripts";
220                         open my $fh, ">", "$mapdir/scripts/shaderlist.txt";
221                         print $fh $shaderlist_new;
222                         close $fh;
223                 }
224
225                 unlink <$m/lm_*>; # delete old external lightmaps
226                 q3map2 '-bsp', '-meta', @{$options->{bsp}},   "$m.map"
227                         or die "-bsp: $?";
228                 if($prescale != 1)
229                 {
230                         q3map2 '-scale', $prescale, "$m.bsp"
231                                 or die "-scale: $?";
232                         rename "${m}_s.bsp", "$m.bsp"
233                                 or die "rename ${m}_s.bsp $m.bsp: $!";
234                 }
235                 if(defined $options->{light})
236                 {
237                         q3map2 '-light',        @{$options->{light}}, "$m.map"
238                                 or die "-light: $?";
239                 }
240                 if(defined $options->{vis})
241                 {
242                         q3map2 '-vis',          @{$options->{vis}},   "$m.map"
243                                 or die "-vis: $?";
244                 }
245                 if($postscale != 1)
246                 {
247                         q3map2 '-scale', $postscale, "$m.bsp"
248                                 or die "-scale: $?";
249                         rename "${m}_s.bsp", "$m.bsp"
250                                 or die "rename ${m}_s.bsp $m.bsp: $!";
251                 }
252
253                 unlink "$m.srf";
254
255                 $restore_shaderlist->();
256                 1;
257         }
258         or do
259         {
260                 $restore_shaderlist->();
261                 die $@;
262         };
263 }