--- Gtk2-GoBoard/GoBoard.pm 2008/06/22 16:25:50 1.2 +++ Gtk2-GoBoard/GoBoard.pm 2008/07/29 10:13:05 1.14 @@ -61,16 +61,17 @@ =cut -our $VERSION = '1.0'; +our $VERSION = '1.01'; no warnings; use strict; use Scalar::Util; use POSIX qw(ceil); +use Carp (); use Gtk2; + use Games::Go::SimpleBoard; -use Carp (); use Glib::Object::Subclass Gtk2::AspectFrame::, @@ -139,20 +140,24 @@ or die "$path: $!"; } +our ($board_img, @black_img, @white_img, $shadow_img, + @triangle_img, @square_img, @circle_img, @cross_img); + sub load_images { - @::black_img = load_image "b-01.png"; - @::white_img = map +(load_image "w-0$_.png"), 1,2,3,4,5; - $::shadow_img = load_image "shadow.png"; - @::triangle_img = map +(load_image "triangle-$_.png"), qw(b w); - @::square_img = map +(load_image "square-$_.png"), qw(b w); - @::circle_img = map +(load_image "circle-$_.png"), qw(b w); - $::board_img = load_image "woodgrain-01.jpg"; + $board_img = load_image "woodgrain-01.jpg"; + @black_img = load_image "b-01.png"; + @white_img = map +(load_image "w-0$_.png"), 1 .. 5; + $shadow_img = load_image "shadow.png"; # also used to fake hoshi points + @triangle_img = map +(load_image "triangle-$_.png"), qw(b w); + @square_img = map +(load_image "square-$_.png" ), qw(b w); + @circle_img = map +(load_image "circle-$_.png" ), qw(b w); + @cross_img = map +(load_image "cross-$_.png" ), qw(b w); } sub INIT_INSTANCE { my $self = shift; - @::black_img + @black_img or load_images; $self->double_buffered (0); @@ -213,7 +218,7 @@ $self->{height} = $self->{canvas}->allocation->height; $self->draw_background; - $self->draw_board (delete $self->{board}, 0) if $self->{board}; + $self->draw_board ({ board => delete $self->{board}, label => delete $self->{label} }, 0) if $self->{board}; $self->{window}->clear_area (0, 0, $self->{width}, $self->{height}); delete $self->{idle}; @@ -224,6 +229,13 @@ 1; } +=item $board->set_board ($games_go_simpleboard) + +Sets the new board position to display from the current position stored in +the L object. + +=cut + sub set_board { my ($self, $board) = @_; @@ -303,17 +315,14 @@ my $pixmap = new Gtk2::Gdk::Pixmap $self->window, $w, $h, -1; - #my $gridcolour = 0x88444400; # black is traditional, but only with overlapping stones my $gridcolour = 0x44444400; # black is traditional, but only with overlapping stones my $labelcolour = 0x88444400; - # we leave enough space for the shadows.. I like smaller stones, and we - # do no need to do the nifty recursive screen updates that cgoban2 does - my $borderw = int ($w / ($size + 1) * 0.5); + my $borderw = int $w / ($size + 1) * 0.5; my $borderh = $borderw; my $w2 = $w - $borderw * 2; my $h2 = $h - $borderh * 2; - my $edge = ceil ($w2 / ($size + 1)); + my $edge = ceil $w2 / ($size + 1); my $ofs = $edge * 0.5; # we need a certain minimum size, and just fudge some formula here @@ -325,16 +334,16 @@ my $pixbuf; - my ($bw, $bh) = ($::board_img->get_width, $::board_img->get_height); + my ($bw, $bh) = ($board_img->get_width, $board_img->get_height); if ($w < $bw && $h < $bh) { $pixbuf = new_pixbuf $w, $h, 0; - $::board_img->copy_area (0, 0, $w, $h, $pixbuf, 0, 0); + $board_img->copy_area (0, 0, $w, $h, $pixbuf, 0, 0); } else { - $pixbuf = scale_pixbuf $::board_img, $w, $h, $::config->{speed} ? 'nearest' : 'bilinear', 0; + $pixbuf = scale_pixbuf $board_img, $w, $h, 'bilinear', 0; # nearest for extra speed } - my $linew = int ($w / 40 / $size); + my $linew = int $w / 40 / $size; # ornamental border... we have time to waste :/ pixbuf_rect $pixbuf, 0xffcc7700, 0, 0, $w-1, $linew, 255; @@ -355,9 +364,9 @@ $x = $kx[$x] - $hs / 2; $y = $ky[$y] - $hs / 2; # we use the shadow mask... not perfect, but I want to finish this - $::shadow_img->composite ($pixbuf, + $shadow_img->composite ($pixbuf, $x, $y, ($hs + 1) x2, $x, $y, - $hs / $::shadow_img->get_width, $hs / $::shadow_img->get_height, + $hs / $shadow_img->get_width, $hs / $shadow_img->get_height, 'bilinear', 255); }; @@ -418,7 +427,7 @@ my $put_stack = sub { my ($x, $y, $dx, $dy, $ox, $oy) = @_; - my $mark = $self->{board}{board}[$x-1][$y-1]; + my $mark = $self->{board}[$x-1][$y-1]; if ($mark & ~MARK_LABEL) { my $stack = $stack{$mark} ||= $self->draw_stack ($mark, $edge); @@ -437,8 +446,7 @@ @area = ($kx[$x] - $ofs, $ky[$y] - $ofs, $edge + $shadow, $edge + $shadow); - @areai = ((ceil $area[0]), (ceil $area[1]), - (int $area[2]), (int $area[3])); # area, integer + @areai = map +(ceil $_), @area; # area, integer $pb = new_pixbuf @areai[2,3]; $self->{backgroundpb}->copy_area (@areai, $pb, 0, 0); @@ -455,19 +463,19 @@ # labels are handled here because they are quite rare # (and we can't draw text into pixbufs easily) - my $mark = $self->{board}{board}[$x-1][$y-1]; + my $mark = $self->{board}[$x-1][$y-1]; if ($mark & MARK_LABEL) { my $white = $mark & MARK_W ? 0 : 0xffffff00; - if ($white) { - $self->center_text ($self->{backgroundpm}, 0, - $areai[0] + $ofs * 1.1, $areai[1] + $ofs * 1.1, - $ofs * 0.7, $self->{board}{label}[$x-1][$y-1]); - } + $self->center_text ($self->{backgroundpm}, 0, + $areai[0] + $ofs * 1.1, $areai[1] + $ofs * 1.1, + $ofs * 0.7, $self->{label}[$x-1][$y-1]) + if $white; + $self->center_text ($self->{backgroundpm}, $white, $areai[0] + $ofs, $areai[1] + $ofs, - $ofs * 0.7, $self->{board}{label}[$x-1][$y-1]); + $ofs * 0.7, $self->{label}[$x-1][$y-1]); } undef $pb; @@ -485,24 +493,24 @@ my $csize = ceil $size; my $shadow = $size * SHADOW; - for my $stone ($mark & MARK_W ? @::white_img : @::black_img) { - my $base = new_pixbuf +(ceil $size + $shadow) x2, 1, 0x00000000; + for my $stone ($mark & MARK_W ? @white_img : @black_img) { + my $base = new_pixbuf +(ceil $csize + $shadow) x2, 1, 0x00000000; # zeroeth the shadow if (~$mark & MARK_GRAYED and $mark & (MARK_B | MARK_W)) { - $::shadow_img->composite ( - $base, $shadow, $shadow, $csize, $csize, $shadow, $shadow, - $size / $::shadow_img->get_width, $size / $::shadow_img->get_height, + $shadow_img->composite ( + $base, ($shadow) x2, $csize, $csize, ($shadow) x2, + $size / $shadow_img->get_width, $size / $shadow_img->get_height, 'bilinear', 128 ); } - for ([MARK_B, $mark & MARK_GRAYED ? 96 : 255, 1], - [MARK_W, $mark & MARK_GRAYED ? 160 : 255, TRAD_SIZE_W / TRAD_SIZE_B]) { + for ([MARK_B, $mark & MARK_GRAYED ? 106 : 255, 1], + [MARK_W, $mark & MARK_GRAYED ? 190 : 255, TRAD_SIZE_W / TRAD_SIZE_B]) { my ($mask, $alpha, $scale) = @$_; if ($mark & $mask) { $stone->composite ( - $base, 0, 0, $csize, $csize, ($size * (1 - $scale) * 0.5 ) x2, + $base, 0, 0, $csize, $csize, ($size * (1 - $scale) * 0.5) x2, $size * $scale / $stone->get_width, $size * $scale / $stone->get_height, 'bilinear', $alpha ); @@ -510,31 +518,32 @@ } # then the small stones (always using the first image) - for ([MARK_SMALL_B, $::black_img[0]], - [MARK_SMALL_W, $::white_img[0]]) { - my ($mask, $img) = @$_; + for ([MARK_SMALL_B, $mark & MARK_SMALL_GRAYED ? 106 : 255, $black_img[0]], + [MARK_SMALL_W, $mark & MARK_SMALL_GRAYED ? 190 : 255, $white_img[0]]) { + my ($mask, $alpha, $img) = @$_; if ($mark & $mask) { $img->composite ( - $base, (int $size / 4) x2, (ceil $size / 2 + 1) x2, ($size / 4) x2, + $base, ($size / 4) x2, (ceil $size / 2 + 1) x2, ($size / 4) x2, $size / $img->get_width / 2, $size / $img->get_height / 2, - 'bilinear', 255 + 'bilinear', $alpha ); } } - # and lastly any markers + # and finally any markers my $dark_bg = ! ! ($mark & MARK_B); - for ([MARK_CIRCLE, $::circle_img[$dark_bg]], - [MARK_TRIANGLE, $::triangle_img[$dark_bg]], - [MARK_SQUARE, $::square_img[$dark_bg]], - [MARK_KO, $::square_img[$dark_bg]]) { + for ([MARK_CIRCLE, $circle_img [$dark_bg]], + [MARK_TRIANGLE, $triangle_img[$dark_bg]], + [MARK_CROSS, $cross_img [$dark_bg]], + [MARK_SQUARE, $square_img [$dark_bg]], + [MARK_KO, $square_img [$dark_bg]]) { my ($mask, $img) = @$_; if ($mark & $mask) { $img->composite ( - $base, 0, 0, $size, $size, 0, 0, + $base, 0, 0, $csize, $csize, 0, 0, $size / $img->get_width, $size / $img->get_height, - 'bilinear', 176 + 'bilinear', $dark_bg ? 176 : 190 ); } } @@ -542,28 +551,36 @@ push @stack, $base; } - \@stack; + \@stack } sub draw_board { my ($self, $new, $dopaint) = @_; - ($self->{board}, my $old) = ($new, $self->{board}); - - my $draw_stone = $self->{draw_stone}; + my $newboard = $new->{board}; + my $newlabel = $new->{label}; if ($self->{backgroundpb}) { + my $draw_stone = $self->{draw_stone}; + + my $oldboard = $self->{board} ||= []; + my $oldlabel = $self->{label} ||= []; + my @areas; my $size1 = $self->{size} - 1; for my $x (0 .. $size1) { - my $old = $old->{board}[$x]; - my $new = $new->{board}[$x]; + my $old = $oldboard->[$x] ||= []; + my $new = $newboard->[$x]; for my $y (0 .. $size1) { - push @areas, $draw_stone->($x+1, $y+1) - if $old->[$y] != $new->[$y]; + next if $old->[$y] == $new->[$y]; + + $old -> [$y] = $new -> [$y]; + $oldlabel->[$x][$y] = $newlabel->[$x][$y]; + + push @areas, $draw_stone->($x+1, $y+1); } } @@ -580,6 +597,12 @@ $self->{window}->clear_area (@$_) for @areas; } } + } else { + no strict 'refs'; + + # straight copy + $self->{board} = [map [@$_], @$newboard]; + $self->{label} = [map [@$_], @$newlabel]; } } @@ -592,11 +615,11 @@ my ($x, $y) = @{$self->{cursorpos}}; - my $mark = $self->{board}{board}[$x][$y]; + my $mark = $self->{board}[$x][$y]; $mark = $self->{cursor}->($mark, $x, $y) if $show; - local $self->{board}{board}[$x][$y] = $mark; + local $self->{board}[$x][$y] = $mark; $self->{window}->clear_area (@{ $self->{draw_stone}->($x + 1, $y + 1) }); } @@ -614,7 +637,9 @@ my $y = int (($y - $self->{ky}[0]) * $size / ($self->{ky}[$size] - $self->{ky}[0]) + 0.5) - 1; my $pos = $self->{cursorpos}; - if ($x != $pos->[0] || $y != $pos->[1]) { + if ((not (defined $pos) && $x >= 0 && $x < $size && $y >= 0 && $y < $size) + || $x != $pos->[0] + || $y != $pos->[1]) { $self->cursor (0); @@ -717,7 +742,8 @@ }; } - kill 9, $$; # required for windows, as a mere exit + # required for windows, as a mere _exit kills your parent process... + kill 9, $$; } else { undef $SOUND_SERVER; return;