r5360 - trunk/misc
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Tue Dec 30 08:48:33 EST 2008
Author: div0
Date: 2008-12-30 08:48:33 -0500 (Tue, 30 Dec 2008)
New Revision: 5360
Added:
trunk/misc/entmerge.pl
Log:
entmerge.pl: ent file management
can make .ent from .map, and merge .ent back into .map
Added: trunk/misc/entmerge.pl
===================================================================
--- trunk/misc/entmerge.pl (rev 0)
+++ trunk/misc/entmerge.pl 2008-12-30 13:48:33 UTC (rev 5360)
@@ -0,0 +1,228 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+# ent file managing tool
+# usage:
+#
+# map -> ent:
+# perl entmerge.pl < mapname.map > mapname.ent
+#
+# ent -> map:
+# perl entmerge.pl mapname.ent < mapname.map > mapname-merged.map
+#
+# bsp -> ent:
+# perl bsptool.pl mapname.bsp -xentities > mapname.ent
+#
+# ent -> bsp:
+# perl bsptool.pl mapname.bsp -rentities < mapname.ent
+
+sub ParseEntity($)
+{
+ my ($fh) = @_;
+
+ my %ent = ( );
+ my @brushes = ( );
+
+ while(<$fh>)
+ {
+ chomp; s/\/\/.*$//; s/^\s+//; s/\s+$//; next if /^$/;
+
+ if(/^\{$/)
+ {
+ # entity starts
+ while(<$fh>)
+ {
+ chomp; s/\/\/.*$//; s/^\s+//; s/\s+$//; next if /^$/;
+
+ if(/^"(.*?)" "(.*)"$/)
+ {
+ # key-value pair
+ $ent{$1} = $2;
+ }
+ elsif(/^\{$/)
+ {
+ my $brush = [];
+ push @brushes, $brush;
+
+ while(<$fh>)
+ {
+ chomp; s/\/\/.*$//; s/^\s+//; s/\s+$//; next if /^$/;
+
+ if(/^\{$/)
+ {
+ # patch?
+ push @$brush, $_;
+
+ while(<$fh>)
+ {
+ chomp; s/\/\/.*$//; s/^\s+//; s/\s+$//; next if /^$/;
+
+ if(/^\}$/)
+ {
+ push @$brush, $_;
+
+ last;
+ }
+ else
+ {
+ push @$brush, $_;
+ }
+ }
+ }
+ elsif(/^\}$/)
+ {
+ # end of brush
+ last;
+ }
+ else
+ {
+ push @$brush, $_;
+ }
+ }
+ }
+ elsif(/^\}$/)
+ {
+ return \%ent, \@brushes;
+ }
+ }
+ }
+ else
+ {
+ die "Unexpected line in top level: $_";
+ }
+ }
+
+ return undef;
+}
+
+sub UnparseEntity($$)
+{
+ my ($ent, $brushes) = @_;
+ my %ent = %$ent;
+
+ my $s = "{\n";
+
+ for(sort keys %ent)
+ {
+ $s .= "\"$_\" \"$ent{$_}\"\n";
+ }
+
+ if(defined $brushes)
+ {
+ for(@$brushes)
+ {
+ $s .= "{\n";
+ $s .= "$_\n" for @$_;
+ $s .= "}\n";
+ }
+ }
+
+ $s .= "}\n";
+ return $s;
+}
+
+my ($in_ent) = @ARGV;
+
+my @submodels = ();
+my @entities = ();
+my @entities_skipped = ();
+
+# THIS part is always a .map file
+my $first = 1;
+my $keeplights;
+for(;;)
+{
+ my ($ent, $brushes) = ParseEntity \*STDIN;
+
+ defined $ent
+ or last;
+
+ if($first && $ent->{classname} eq 'worldspawn')
+ {
+ $keeplights = $ent->{_keeplights};
+ @submodels = ($brushes);
+ }
+ else
+ {
+ if($first)
+ {
+ push @entities, { classname => "worldspawn" };
+ @submodels = ([]);
+ }
+
+ if($ent->{classname} eq 'worldspawn')
+ {
+ $ent->{classname} = "worldspawn_renamed";
+ }
+
+ if(grep { $_ eq $ent->{classname} } (qw/group_info func_group misc_model _decal _skybox/, ($keeplights ? qw// : qw/light/)))
+ {
+ push @entities_skipped, [$ent, $brushes];
+ next;
+ }
+
+ if(@$brushes)
+ {
+ my $i = @submodels;
+ push @submodels, $brushes;
+ $ent->{model} = sprintf "*%d", $i;
+ }
+ }
+
+ push @entities, $ent;
+
+ $first = 0;
+}
+
+if(defined $in_ent)
+{
+ # translate map using ent to map
+ open my $fh, "<", $in_ent
+ or die "$in_ent: $!";
+
+ # THIS part is always an .ent file now
+ my @entities_entfile = ();
+ $first = 1;
+ while(<STDIN>)
+ {
+ my ($ent, $brushes) = ParseEntity $fh;
+ push @entities_entfile, $ent;
+ $first = 0;
+ }
+ close $fh;
+
+ $first = 1;
+ for(@entities)
+ {
+ my %e = %$_;
+ my $submodel = undef;
+ if($first)
+ {
+ $submodel = $submodels[0];
+ }
+ elsif($e{model} =~ /^\*(\d+)$/)
+ {
+ $submodel = $submodels[$1];
+ delete $e{model};
+ }
+ print UnparseEntity \%e, $submodel;
+ $first = 0;
+ }
+ for(@entities_skipped)
+ {
+ print UnparseEntity $_->[0], $_->[1];
+ $first = 0;
+ }
+}
+else
+{
+ # translate map to ent
+ $first = 1;
+ for(@entities)
+ {
+ print UnparseEntity $_, undef;
+ $first = 0;
+ }
+}
More information about the nexuiz-commits
mailing list