XXX: scmap: restore metadata marking (era-dependant styling) master
authorMischa POSLAWSKY <perl@shiar.org>
Thu, 12 Feb 2009 05:08:46 +0000 (06:08 +0100)
committerMischa POSLAWSKY <perl@shiar.org>
Thu, 12 Feb 2009 15:29:00 +0000 (16:29 +0100)
scmap

diff --git a/scmap b/scmap
index f636b25742250bf6d5fd8c921cc9bff38eac451e..33f7f8b94844cf1a7c236d3b77243e2e30c6c41c 100755 (executable)
--- a/scmap
+++ b/scmap
@@ -62,6 +62,35 @@ my %mapsep = (
        ascii => '',
 );
 
+use Inline with => 'Imager';
+use Inline C => <<'EOS';
+void blendpixel(Imager img, int offset, Imager::Color color) {
+       int ch;
+       float opacity = (float)color->channel[3] / 255;
+       for (ch = 0; ch < img->channels; ++ch) {
+               img->idata[offset * img->channels + ch] *= 1 - opacity;
+               img->idata[offset * img->channels + ch] += color->channel[ch] * opacity;
+       }
+       return;
+}
+
+EOS
+
+my %UNITINFO = ( # unitid => color|image, width, height
+       176 => [min => [ 47, 195, 255], 2, 1], # minerals
+       188 => [gas => [ 15, 255,  63], 2, 1], # gas
+       214 => [pos => [255, 255,   0], 2, 2], # start pos
+);
+$UNITINFO{$_} = $UNITINFO{176} for 177, 178;
+
+my $STYLE = {
+               wall => [0, 0, 255, 127],
+               edge => [0, 0, 255, 15],
+               ramp => [0, 255, 0, 47],
+               rock => [255, 0, 0, 255],
+};
+$_ = Imager::Color->new(@$_) for values %$STYLE;
+
 if (defined $mapsep{$SHOWMAP}) {
        my $MAPCHARSEP = $mapsep{$SHOWMAP};
 
@@ -89,6 +118,31 @@ if (defined $mapsep{$SHOWMAP}) {
 
                        # 512x512 ~ 7s
                        my $tile = $tileset->tile($_);
+BLENDTILE:
+                       for (my $offset = 0; $offset < 4*4; $offset++) {
+                               for (my $y = 0; $y < 4; $y++) {
+                                       my $subtype = $tile->{subtype}->[$offset];
+                                       if ($subtype & 8) {
+                                               # obstructions
+                                               blendpixel($tile->{sprite}, $offset, $STYLE->{wall});
+                                       }
+                                       elsif (($subtype & 1) == 0) {
+                                               # unwalkable
+                                               blendpixel($tile->{sprite}, $offset, $STYLE->{edge});
+                                       }
+                                       elsif ($subtype & 16) {
+                                               # ramps
+                                               my $mask = Imager->new(xsize => 4, ysize => 4, channels => 4);
+                                               $mask->box(color => $STYLE->{ramp}, filled => 1);
+                                               $tile->{sprite}->rubthrough(src => $mask);
+                                               last BLENDTILE;
+                                       }
+                                       elsif ($tile->{build}) {
+                                               # unbuildable
+                                               blendpixel($tile->{sprite}, $offset, $STYLE->{rock});
+                                       }
+                               }
+                       }
                        $img->paste(src => $tile->{sprite}, left => $x*4, top => $y*4);
 
                        # 4096x4096 ~ 75s
@@ -107,6 +161,59 @@ if (defined $mapsep{$SHOWMAP}) {
                        }
                }
 
+               my $overlaymin = Imager->new(
+                       xsize => $img->getwidth,
+                       ysize => $img->getheight,
+                       channels => 4,
+               );
+               my $overlaygas = $overlaymin->copy;
+               for my $unit ($map->units) {
+                       my $info = $UNITINFO{ $unit->{id} } or next;
+                       my ($name, $color, $xsize, $ysize) = @$info or next;
+                       if ($name eq 'min') {
+                               next if $unit->{amount} <= 8;
+                               $overlaymin->circle(
+                                       x      => 4 * ($unit->{x} + $xsize/2),
+                                       y      => 4 * ($unit->{y} + $ysize/2),
+                                       r      => 4 * ($unit->{amount} <= 40 ? 2 : 4),
+                                       color  => $color,
+                                       filled => 1,
+                                       aa     => 1,
+                               );
+                       }
+                       elsif ($name eq 'gas') {
+                               $overlaygas->circle(
+                                       x      => 4 * ($unit->{x} + $xsize/2),
+                                       y      => 4 * ($unit->{y} + $ysize/2),
+                                       r      => 4 * ($unit->{amount} <= 40 ? 2 : 4),
+                                       color  => $color,
+                                       filled => 1,
+                                       aa     => 1,
+                               );
+                       }
+               }
+               $img->compose(src => $overlaymin, opacity => 0.1875);
+               $img->compose(src => $overlaygas, opacity => 0.125);
+
+               for my $unit ($map->units) {
+                       my $info = $UNITINFO{ $unit->{id} }
+                               or warn("No unit styling for unit #$unit->{id}"), next;
+                       my ($name, $color, $xsize, $ysize, $sprite) = @$info;
+                       if ($sprite) {
+                               $img->paste(src => $sprite, x => $unit->{x}, y => $unit->{y});
+                       }
+                       else {
+                               $img->box(
+                                       xmin   => 4 * $unit->{x},
+                                       ymin   => 4 * $unit->{y},
+                                       xmax   => 4 * ($unit->{x} + ($xsize || 1)),
+                                       ymax   => 4 * ($unit->{y} + ($ysize || 1)),
+                                       color  => $color,
+                                       filled => 1,
+                               );
+                       }
+               }
+
                $img->write(fd => fileno(STDOUT), type => 'png')
                        or die 'Cannot output image: ', $img->errstr;
        }