package GCE::MapEditor; =head1 NAME GCE::MapEditor - the map editing widget =cut use Gtk2; use Gtk2::Gdk::Keysyms; use Gtk2::SimpleMenu; use Crossfire; use Crossfire::Map; use Crossfire::MapWidget; use GCE::AttrEdit; use Glib::Object::Subclass Gtk2::VBox, ; use strict; sub INIT_INSTANCE { my ($self) = @_; my $map = new Crossfire::MapWidget; # XXX: Make a nicer pick-view (with picture) $self->pack_start (my $lbl = Gtk2::Label->new ("no selection"), 0, 1, 0); $self->{pick_view} = $lbl; $self->pack_start ($map, 1, 1, 0); $self->{map} = $map; $map->signal_connect (key_press_event => sub { my ($map, $event) = @_; $event->keyval == $Gtk2::Gdk::Keysyms{Shift_L} and $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_QUESTION_ARROW')); $event->keyval == $Gtk2::Gdk::Keysyms{Control_L} and $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_HAND2')); }); # XXX: What happens if the release got lost? $map->signal_connect (key_release_event => sub { my ($map, $event) = @_; $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR')); }); $map->signal_connect (button_press_event => sub { my ($map, $event) = @_; my ($x, $y) = $map->coord ($event->x, $event->y); if ($event->button == 1) { my $s = map_get_tile_stack ($self->{map}, $x, $y); if ($event->state * "control-mask") { $self->update_pick ($s->[-1]) if @$s; } unless ($event->state * "shift-mask") { $map->disable_tooltip unless $self->{draw_mode}; $self->{draw_mode} = [1, $x, $y]; $self->place_pick ($x, $y); $s = map_get_tile_stack ($self->{map}, $x, $y); } $GCE::MainWindow::MAINWIN->update_attr_editor ($s->[-1]) if @$s; $GCE::MainWindow::MAINWIN->update_stack_view ($self, $s, $x, $y); return 1; } elsif ($event->button == 3) { $map->disable_tooltip unless $self->{draw_mode}; $self->{draw_mode} = [2, $x, $y]; $self->delete_arch ($x, $y); my $s = map_get_tile_stack ($self->{map}, $x, $y); $GCE::MainWindow::MAINWIN->update_attr_editor ($s->[-1]) if @$s; $GCE::MainWindow::MAINWIN->update_stack_view ($self, $s, $x, $y); return 1; } 0 }); $map->signal_connect_after (motion_notify_event => sub { my ($map, $event) = @_; $self->{draw_mode} or return; my ($X, $Y) = @{$self->{draw_mode}}[1,2]; my ($x, $y) = $map->coord ($map->get_pointer); while ($x != $X || $y != $Y) { $X++ if $X < $x; $X-- if $X > $x; $Y++ if $Y < $y; $Y-- if $Y > $y; if ($self->{draw_mode}[0] == 1) { $self->place_pick ($X, $Y); } elsif ($self->{draw_mode}[0] == 2) { $self->delete_arch ($X, $Y); } } @{$self->{draw_mode}}[1,2] = ($X, $Y); 1 }); $map->signal_connect (button_release_event => sub { my ($map, $event) = @_; $map->enable_tooltip if delete $self->{draw_mode}; 0 }); } sub set_place_arch { my ($self, $arch) = @_; $self->{pick_arch} = $arch; } sub delete_arch { my ($self, $x, $y) = @_; defined $self->{map} or return 0; my $s = map_pop_tile_stack ($self->{map}, $x, $y); $self->{map}->update_map ($x, $y, 1, 1); } sub place_pick { my ($self, $x, $y) = @_; defined $self->{map} and defined $self->{pick_arch} or return 0; my $s = map_get_tile_stack ($self->{map}, $x, $y); # XXX: Do a deep clone? my $arch = { _name => $self->{pick_arch}->{_name} }; if (not defined ($s->[-1]) or $s->[-1]->{_name} ne $arch->{_name}) { map_push_tile_stack ($self->{map}, $x, $y, $arch); } $self->{map}->update_map ($x, $y, 1, 1); } sub open_map { my ($self, $path) = @_; $self->{map}->set_map (new_from_file Crossfire::Map $path); } sub update_pick { my ($self, $arch) = @_; $self->{pick_arch} = $arch; $self->{pick_view}->set_text ($arch->{_name}); } =head1 AUTHOR Marc Lehmann http://home.schmorp.de/ Robin Redeker http://www.ta-sa.org/ =cut 1;