ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/MapEditor.pm
Revision: 1.16
Committed: Sun Mar 12 13:40:34 2006 UTC (18 years, 3 months ago) by elmex
Branch: MAIN
Changes since 1.15: +1 -0 lines
Log Message:
Simple attribute editing now works. Still missing: bitmasks and there
are some refreshbugs in the StackView and AttrEdit. Should be refreshed
when the map detects changes...

File Contents

# User Rev Content
1 elmex 1.1 package GCE::MapEditor;
2    
3     =head1 NAME
4    
5     GCE::MapEditor - the map editing widget
6    
7     =cut
8    
9     use Gtk2;
10     use Gtk2::Gdk::Keysyms;
11     use Gtk2::SimpleMenu;
12    
13     use Crossfire;
14 root 1.3 use Crossfire::Map;
15 elmex 1.1 use Crossfire::MapWidget;
16    
17     use GCE::AttrEdit;
18    
19 elmex 1.4 use Glib::Object::Subclass
20 elmex 1.6 Gtk2::Window;
21 elmex 1.1
22     use strict;
23    
24 root 1.9 sub build_menu {
25     my ($self) = @_;
26    
27     my $menu_tree = [
28     _File => {
29     item_type => '<Branch>',
30     children => [
31     "_Save" => {
32 root 1.10 callback => sub { $self->save_map },
33 root 1.9 accelerator => '<ctrl>S'
34     },
35 root 1.10 "Save As" => {
36     callback => sub { $self->save_map_as },
37     },
38 root 1.13 "Close" => {
39     callback => sub { $self->delete; 1 },
40     },
41 root 1.10 ]
42 root 1.9 },
43     _Edit => {
44     item_type => '<Branch>',
45     children => [
46     "_Undo" => {
47     callback => sub { $self->undo },
48     accelerator => "<ctrl>Z"
49     },
50     "_Redo" => {
51     callback => sub { $self->redo },
52     accelerator => "<ctrl>Y"
53     },
54    
55     ]
56     },
57    
58     ];
59    
60     my $men =
61     Gtk2::SimpleMenu->new (
62     menu_tree => $menu_tree,
63     default_callback => \&default_cb,
64     );
65    
66     $self->add_accel_group ($men->{accel_group});
67    
68     return $men->{widget};
69     }
70    
71 elmex 1.1 sub INIT_INSTANCE {
72     my ($self) = @_;
73    
74 elmex 1.6 $self->set_title ('gce - map editor');
75     $self->add (my $vb = Gtk2::VBox->new);
76 elmex 1.1
77 root 1.13 $self->signal_connect (delete_event => sub { $self->delete });
78    
79 root 1.9 $vb->pack_start (my $menu = $self->build_menu, 0, 1, 0);
80    
81     $vb->pack_start (my $map = $self->{map} = Crossfire::MapWidget->new, 1, 1, 0);
82    
83     $map->signal_connect (button_press_event => sub {
84     my ($map, $event) = @_;
85    
86     my ($x, $y) = $map->coord ($event->x, $event->y);
87     my $as = $map->get ($x, $y);
88    
89     my $btn = $event->button;
90    
91     if ((not $self->{draw_mode})
92     and $btn != 2
93     and my $ea = $::MAINWIN->{sel_editaction}) {
94    
95 elmex 1.15 $ea->begin ($map, $x, $y, $btn)
96     if $x >= 0 and $y >= 0 and $x < $map->{map}{width} and $y < $map->{map}{height};
97 elmex 1.1
98 root 1.9 $self->{draw_mode} = [$ea, $x, $y, $btn];
99 elmex 1.1
100 root 1.9 $ea->want_cursor
101     or $map->disable_tooltip;
102 elmex 1.4
103 root 1.9 if ($ea->special_arrow) {
104 elmex 1.4
105 root 1.9 $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ($ea->special_arrow));
106     #'GDK_QUESTION_ARROW'));
107     }
108    
109     return 1;
110     }
111    
112     0
113     });
114    
115     $map->signal_connect_after (motion_notify_event => sub {
116     my ($map, $event) = @_;
117    
118     $self->{draw_mode}
119     or return;
120    
121     my ($X, $Y) = @{$self->{draw_mode}}[1,2];
122     my ($x, $y) = $map->coord ($map->get_pointer);
123 elmex 1.4
124 root 1.9 while ($x != $X || $y != $Y) {
125 elmex 1.4
126 root 1.9 $X++ if $X < $x;
127     $X-- if $X > $x;
128     $Y++ if $Y < $y;
129     $Y-- if $Y > $y;
130 elmex 1.4
131 elmex 1.15 $self->{draw_mode}[0]->edit ($map, $X, $Y, $self->{draw_mode}[3])
132     if $X >= 0 and $Y >= 0 and $X < $map->{map}{width} and $Y < $map->{map}{height};
133 root 1.9 }
134 elmex 1.4
135 root 1.9 @{$self->{draw_mode}}[1,2] = ($X, $Y);
136 elmex 1.1
137 root 1.9 1
138     });
139 elmex 1.1
140 root 1.9 $map->signal_connect (button_release_event => sub {
141     my ($map, $event) = @_;
142 elmex 1.1
143 root 1.9 if ($self->{draw_mode}
144     and my $ea = $self->{draw_mode}[0]
145     and $self->{draw_mode}[3] == $event->button) {
146 elmex 1.1
147 root 1.9 my ($x, $y) = $map->coord ($map->get_pointer);
148 elmex 1.4
149 root 1.9 $ea->end ($map, $x, $y, $event->button);
150 elmex 1.1
151 root 1.9 if ($ea->special_arrow) {
152 elmex 1.1
153 root 1.9 # XXX: Get the original cursor and insert it here
154     $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR'));
155     }
156 elmex 1.1
157 root 1.9 delete $self->{draw_mode};
158 elmex 1.4
159 root 1.9 $ea->want_cursor
160     or $map->enable_tooltip;
161 elmex 1.1
162 root 1.9 return 1;
163     }
164 elmex 1.1
165 root 1.9 0
166     });
167     }
168 elmex 1.8
169 elmex 1.16 # FIXME: Fix the automatic update of the attribute editor! and also the stack view!
170 root 1.9 sub undo {
171     my ($self) = @_;
172 elmex 1.8
173 root 1.9 my $map = $self->{map}; # the Crossfire::MapWidget
174 elmex 1.1
175 root 1.9 $map->{undo_stack_pos}
176     or return;
177 elmex 1.1
178 root 1.9 $map->change_swap ($map->{undo_stack}[--$map->{undo_stack_pos}]);
179     }
180 elmex 1.1
181 root 1.9 sub redo {
182     my ($self) = @_;
183 elmex 1.7
184 root 1.9 my $map = $self->{map}; # the Crossfire::MapWidget
185 elmex 1.7
186 elmex 1.14 $map->{undo_stack}
187     and $map->{undo_stack_pos} < @{$map->{undo_stack}}
188     or return;
189 elmex 1.1
190 root 1.9 $map->change_swap ($map->{undo_stack}[$map->{undo_stack_pos}++]);
191 root 1.3 }
192    
193     sub delete_arch {
194     my ($self, $x, $y) = @_;
195    
196     defined $self->{map}
197     or return 0;
198    
199 root 1.5 my $as = $self->{map}->get ($x, $y);
200     pop @$as;
201     $self->{map}->set ($x, $y, $as);
202 root 1.3 }
203    
204     sub place_pick {
205     my ($self, $x, $y) = @_;
206    
207 root 1.9 my $pick = $::MAINWIN->get_pick;
208 root 1.5 my $as = $self->{map}->get ($x, $y);
209 root 1.3
210 elmex 1.6 my $arch = { _name => $pick->{_name} };
211 root 1.3
212 root 1.5 push @$as, $arch
213     unless @$as && $as->[-1]->{_name} eq $arch->{_name};
214 root 1.3
215 root 1.5 $self->{map}->set ($x, $y, $as);
216 root 1.3 }
217    
218 root 1.13 sub delete {
219     my ($self) = @_;
220    
221     # check and modla dialog if "dirty"
222    
223     $self->destroy;
224     }
225    
226 root 1.3 sub open_map {
227     my ($self, $path) = @_;
228    
229 root 1.13 $self->{path} = $path;
230 elmex 1.15 $self->{map}->set_map (my $m = new_from_file Crossfire::Map $path);
231     require Data::Dumper;
232 root 1.3 }
233    
234 root 1.13 sub save_map {
235     my ($self) = @_;
236    
237     $self->{map}{map}->write_file ($self->{path});
238     }
239    
240     sub save_map_as {
241     my ($self) = @_;
242     warn "save_map_as nyi\n";
243     }
244    
245 elmex 1.1 =head1 AUTHOR
246    
247     Marc Lehmann <schmorp@schmorp.de>
248     http://home.schmorp.de/
249    
250     Robin Redeker <elmex@ta-sa.org>
251     http://www.ta-sa.org/
252    
253     =cut
254     1;
255