]> icculus.org git repositories - divverent/nexuiz.git/blob - misc/tools/nexuiz-map-compiler
improve nexuiz-map-compiler
[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", 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         if($prescale != 1 or $postscale != 1)
136         {
137                 open my $checkfh, "<", "$m.map"
138                         or die "open $m.map: $!";
139                 my $keeplights = 0;
140                 while(<$checkfh>)
141                 {
142                         /^\s*"_keeplights"\s+"1"\s*$/
143                                 or next;
144                         $keeplights = 1;
145                 }
146                 close $checkfh;
147                 die "$m does not define _keeplights to 1"
148                         unless $keeplights;
149         }
150
151         my %shaders = map { m!/([^/.]*)\.shader(?:$)! ? ($1 => 1) : () } glob "../scripts/*.shader";
152         if(!-f "$NEXUIZDIR/data/scripts/shaderlist.txt")
153         {
154                 # possibly extract the shader list from a pk3?
155                 local $ENV{D} = $NEXUIZDIR;
156                 system q{cd "$D" && for X in data/data*.pk3; do unzip -o "$X" scripts/shaderlist.txt; done};
157         }
158         open my $shaderlist, "+<", "$NEXUIZDIR/data/scripts/shaderlist.txt"
159                 or die "open $NEXUIZDIR/data/scripts/shaderlist.txt: $!";
160         my $previous_shaderlist = "";
161         while(<$shaderlist>)
162         {
163                 $previous_shaderlist .= $_;
164                 y/\r\n//d;
165                 delete $shaders{$_};
166         }
167         my $restore_shaderlist = sub
168         {
169                 open $shaderlist, ">", "$NEXUIZDIR/data/scripts/shaderlist.txt";
170                 print $shaderlist $previous_shaderlist;
171                 close $shaderlist;
172         };
173         local $SIG{INT} = sub
174         {
175                 print "SIGINT caught, cleaning up...\n";
176                 $restore_shaderlist->();
177                 exit 0;
178         };
179         eval
180         {
181                 for(keys %shaders)
182                 {
183                         print $shaderlist "$_\n";
184                 }
185                 close $shaderlist;
186
187                 unlink <$m/lm_*>; # delete old external lightmaps
188                 q3map2 '-bsp', '-meta', @{$options->{bsp}},   "$m.map"
189                         or die "-bsp: $?";
190                 if($prescale != 1)
191                 {
192                         q3map2 '-scale', $prescale, "$m.bsp"
193                                 or die "-scale: $?";
194                         rename "${m}_s.bsp", "$m.bsp"
195                                 or die "rename ${m}_s.bsp $m.bsp: $!";
196                 }
197                 if(defined $options->{light})
198                 {
199                         q3map2 '-light',        @{$options->{light}}, "$m.map"
200                                 or die "-light: $?";
201                 }
202                 if(defined $options->{vis})
203                 {
204                         q3map2 '-vis',          @{$options->{vis}},   "$m.map"
205                                 or die "-vis: $?";
206                 }
207                 if($postscale != 1)
208                 {
209                         q3map2 '-scale', $postscale, "$m.bsp"
210                                 or die "-scale: $?";
211                         rename "${m}_s.bsp", "$m.bsp"
212                                 or die "rename ${m}_s.bsp $m.bsp: $!";
213                 }
214
215                 unlink "$m.srf";
216
217                 $restore_shaderlist->();
218                 1;
219         }
220         or do
221         {
222                 $restore_shaderlist->();
223                 die $@;
224         };
225 }