ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/gde/GCE/MapEditor.pm
Revision: 1.18
Committed: Sun Mar 12 23:32:58 2006 UTC (20 years, 7 months ago) by elmex
Branch: MAIN
Changes since 1.17: +11 -4 lines
Log Message:
implemented file->new and implemented attredit

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 elmex 1.17 accelerator => "<ctrl>Z"
49 root 1.9 },
50     "_Redo" => {
51     callback => sub { $self->redo },
52 elmex 1.17 accelerator => "<ctrl>Y"
53     },
54     "_Map Properties" => {
55     callback => sub { $self->open_map_prop },
56     accelerator => "<ctrl>P"
57     },
58     "_Map Resize" => {
59     callback => sub { $self->open_resize_map },
60     accelerator => "<ctrl>R"
61 root 1.9 },
62     ]
63     },
64    
65     ];
66    
67     my $men =
68     Gtk2::SimpleMenu->new (
69     menu_tree => $menu_tree,
70     default_callback => \&default_cb,
71     );
72    
73     $self->add_accel_group ($men->{accel_group});
74    
75     return $men->{widget};
76     }
77    
78 elmex 1.1 sub INIT_INSTANCE {
79     my ($self) = @_;
80    
81 elmex 1.6 $self->set_title ('gce - map editor');
82     $self->add (my $vb = Gtk2::VBox->new);
83 elmex 1.1
84 root 1.13 $self->signal_connect (delete_event => sub { $self->delete });
85    
86 root 1.9 $vb->pack_start (my $menu = $self->build_menu, 0, 1, 0);
87    
88     $vb->pack_start (my $map = $self->{map} = Crossfire::MapWidget->new, 1, 1, 0);
89    
90     $map->signal_connect (button_press_event => sub {
91     my ($map, $event) = @_;
92    
93     my ($x, $y) = $map->coord ($event->x, $event->y);
94     my $as = $map->get ($x, $y);
95    
96     my $btn = $event->button;
97    
98     if ((not $self->{draw_mode})
99     and $btn != 2
100     and my $ea = $::MAINWIN->{sel_editaction}) {
101    
102 elmex 1.15 $ea->begin ($map, $x, $y, $btn)
103     if $x >= 0 and $y >= 0 and $x < $map->{map}{width} and $y < $map->{map}{height};
104 elmex 1.1
105 root 1.9 $self->{draw_mode} = [$ea, $x, $y, $btn];
106 elmex 1.1
107 root 1.9 $ea->want_cursor
108     or $map->disable_tooltip;
109 elmex 1.4
110 root 1.9 if ($ea->special_arrow) {
111 elmex 1.4
112 root 1.9 $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ($ea->special_arrow));
113     #'GDK_QUESTION_ARROW'));
114     }
115    
116     return 1;
117     }
118    
119     0
120     });
121    
122     $map->signal_connect_after (motion_notify_event => sub {
123     my ($map, $event) = @_;
124    
125     $self->{draw_mode}
126     or return;
127    
128     my ($X, $Y) = @{$self->{draw_mode}}[1,2];
129     my ($x, $y) = $map->coord ($map->get_pointer);
130 elmex 1.4
131 root 1.9 while ($x != $X || $y != $Y) {
132 elmex 1.4
133 root 1.9 $X++ if $X < $x;
134     $X-- if $X > $x;
135     $Y++ if $Y < $y;
136     $Y-- if $Y > $y;
137 elmex 1.4
138 elmex 1.15 $self->{draw_mode}[0]->edit ($map, $X, $Y, $self->{draw_mode}[3])
139     if $X >= 0 and $Y >= 0 and $X < $map->{map}{width} and $Y < $map->{map}{height};
140 root 1.9 }
141 elmex 1.4
142 root 1.9 @{$self->{draw_mode}}[1,2] = ($X, $Y);
143 elmex 1.1
144 root 1.9 1
145     });
146 elmex 1.1
147 root 1.9 $map->signal_connect (button_release_event => sub {
148     my ($map, $event) = @_;
149 elmex 1.1
150 root 1.9 if ($self->{draw_mode}
151     and my $ea = $self->{draw_mode}[0]
152     and $self->{draw_mode}[3] == $event->button) {
153 elmex 1.1
154 root 1.9 my ($x, $y) = $map->coord ($map->get_pointer);
155 elmex 1.4
156 root 1.9 $ea->end ($map, $x, $y, $event->button);
157 elmex 1.1
158 root 1.9 if ($ea->special_arrow) {
159 elmex 1.1
160 root 1.9 # XXX: Get the original cursor and insert it here
161     $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR'));
162     }
163 elmex 1.1
164 root 1.9 delete $self->{draw_mode};
165 elmex 1.4
166 root 1.9 $ea->want_cursor
167     or $map->enable_tooltip;
168 elmex 1.1
169 root 1.9 return 1;
170     }
171 elmex 1.1
172 root 1.9 0
173     });
174     }
175 elmex 1.8
176 elmex 1.16 # FIXME: Fix the automatic update of the attribute editor! and also the stack view!
177 root 1.9 sub undo {
178     my ($self) = @_;
179 elmex 1.8
180 root 1.9 my $map = $self->{map}; # the Crossfire::MapWidget
181 elmex 1.1
182 root 1.9 $map->{undo_stack_pos}
183     or return;
184 elmex 1.1
185 root 1.9 $map->change_swap ($map->{undo_stack}[--$map->{undo_stack_pos}]);
186     }
187 elmex 1.1
188 root 1.9 sub redo {
189     my ($self) = @_;
190 elmex 1.7
191 root 1.9 my $map = $self->{map}; # the Crossfire::MapWidget
192 elmex 1.7
193 elmex 1.14 $map->{undo_stack}
194     and $map->{undo_stack_pos} < @{$map->{undo_stack}}
195     or return;
196 elmex 1.1
197 root 1.9 $map->change_swap ($map->{undo_stack}[$map->{undo_stack_pos}++]);
198 root 1.3 }
199    
200     sub delete_arch {
201     my ($self, $x, $y) = @_;
202    
203     defined $self->{map}
204     or return 0;
205    
206 root 1.5 my $as = $self->{map}->get ($x, $y);
207     pop @$as;
208     $self->{map}->set ($x, $y, $as);
209 root 1.3 }
210    
211     sub place_pick {
212     my ($self, $x, $y) = @_;
213    
214 root 1.9 my $pick = $::MAINWIN->get_pick;
215 root 1.5 my $as = $self->{map}->get ($x, $y);
216 root 1.3
217 elmex 1.6 my $arch = { _name => $pick->{_name} };
218 root 1.3
219 root 1.5 push @$as, $arch
220     unless @$as && $as->[-1]->{_name} eq $arch->{_name};
221 root 1.3
222 root 1.5 $self->{map}->set ($x, $y, $as);
223 root 1.3 }
224    
225 root 1.13 sub delete {
226     my ($self) = @_;
227    
228     # check and modla dialog if "dirty"
229    
230     $self->destroy;
231     }
232    
233 root 1.3 sub open_map {
234     my ($self, $path) = @_;
235    
236 elmex 1.18 if (ref $path) {
237     print "REFE\n";
238     $self->{map}->set_map ($path);
239     print "UNREF\n";
240    
241     } else {
242     $self->{path} = $path;
243 elmex 1.17 # print "OPENMAP $path\n";
244 elmex 1.18 $self->{map}->set_map (my $m = new_from_file Crossfire::Map $path);
245     require Data::Dumper;
246     # print "FOO:" .Data::Dumper::Dumper ($m) . "\n";
247     }
248 root 1.3 }
249    
250 root 1.13 sub save_map {
251     my ($self) = @_;
252    
253     $self->{map}{map}->write_file ($self->{path});
254     }
255    
256     sub save_map_as {
257     my ($self) = @_;
258     warn "save_map_as nyi\n";
259     }
260    
261 elmex 1.17 sub _add_prop_entry {
262     my ($self, $table, $idx, $key, $desc, $type, $changecb) = @_;
263    
264    
265     my $edwid;
266    
267     if ($type eq 'string') {
268     $table->attach_defaults (my $lbl = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1);
269     $edwid = Gtk2::Entry->new;
270     $edwid->set_text ($self->{map}{map}{info}{$key});
271     $edwid->signal_connect (changed => sub {
272     $self->{map}{map}{info}{$key} = $_[0]->get_text;
273     if ($changecb) {
274     print "CHANGECB " . $_[0]->get_text . "\n";
275     $changecb->($_[0]->get_text);
276     }
277     });
278     $table->attach_defaults ($edwid, 1, 2, $idx, $idx + 1);
279    
280     } elsif ($type eq 'button') {
281     $table->attach_defaults (my $b = Gtk2::Button->new_with_label ($desc), 0, 2, $idx, $idx + 1);
282     $b->signal_connect (clicked => ($changecb || sub {}));
283    
284     } elsif ($type eq 'label') {
285     $table->attach_defaults (my $lbl = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1);
286     $edwid = Gtk2::Label->new ($self->{map}{map}{info}{$key});
287     $table->attach_defaults ($edwid, 1, 2, $idx, $idx + 1);
288    
289     } else {
290     $edwid = Gtk2::Label->new ("FOO");
291     }
292     }
293    
294     sub open_resize_map {
295     my ($self) = @_;
296    
297     my $w = Gtk2::Window->new ('toplevel');
298     $w->set_default_size (250, 150);
299     $w->add (my $sw = Gtk2::ScrolledWindow->new);
300     $sw->add_with_viewport (my $v = Gtk2::VBox->new);
301     $sw->set_policy ('automatic', 'automatic');
302     $v->pack_start (my $t = Gtk2::Table->new (2, 10), 0, 0, 0);
303    
304     my $i = 0;
305     for (
306     [qw/width Width string/],
307     [qw/height Height string/],
308     [qw/save Save button/,
309     sub {
310     $self->{map}{map}->resize ($self->{map}{map}{info}{width}, $self->{map}{map}{info}{height});
311     $self->{map}->invalidate_all
312     }
313     ],
314     )
315     {
316     $self->_add_prop_entry ($t, $i++, @$_);
317     }
318    
319     $w->show_all;
320     }
321    
322     sub open_map_prop {
323     my ($self) = @_;
324    
325    
326     my $w = Gtk2::Window->new ('toplevel');
327     $w->set_default_size (500, 500);
328     $w->add (my $sw = Gtk2::ScrolledWindow->new);
329     $sw->add_with_viewport (my $v = Gtk2::VBox->new);
330     $sw->set_policy ('automatic', 'automatic');
331     $v->pack_start (my $t = Gtk2::Table->new (2, 10), 0, 0, 0);
332    
333     my $i = 0;
334     for (
335     [qw/name Name string/],
336     [qw/region Region string/],
337     [qw/difficulty Difficulty string/],
338     [qw/width Width label/], # sub { $self->{map}{map}->resize ($_[0], $self->{map}{map}{height}) }],
339     [qw/height Height label/],# sub { $self->{map}{map}->resize ($self->{map}{map}{width}, $_[0]) }],
340     [qw/msg Text text/],
341     [qw/tile_path_1 Northpath string/],
342     [qw/tile_path_2 Eastpath string/],
343     [qw/tile_path_3 Southpath string/],
344     [qw/tile_path_4 Westpath string/],
345     [qw/tile_path_5 Toppath string/],
346     [qw/tile_path_6 Bottompath string/],
347     )
348     {
349     $self->_add_prop_entry ($t, $i++, @$_);
350     }
351    
352     $w->show_all;
353     }
354    
355     # 'info' => {
356     # 'windspeed' => '10',
357     # 'outdoor' => '1',
358     # 'width' => '20',
359     # 'pressure' => '8',
360     # 'test' => '',
361     # 'tile_path_2' => 'east',
362     # 'tile_path_3' => 'south',
363     # 'enter_y' => '2',
364     # 'tile_path_6' => 'bottom',
365     # 'enter_x' => '1',
366     # 'tile_path_5' => 'top',
367     # 'darkness' => '4',
368     # 'maplore' => '',
369     # 'sky' => '12',
370     # 'winddir' => '11',
371     # 'unique' => '1',
372     # 'msg' => 'Creator: CF Java FUCK Map Editor
373     #Date: 3/12/2006
374     #',
375     # 'difficulty' => '3',
376     # 'humid' => '9',
377     # 'endmaplore' => '',
378     # 'fixed_resettime' => '1',
379     # 'name' => 'test',
380     # 'region' => 'REGION',
381     # 'height' => '40',
382     # 'reset_timeout' => '6',
383     # '_name' => 'map',
384     # 'swap_time' => '5',
385     # 'temp' => '7',
386     # 'tile_path_4' => 'west',
387     # 'tile_path_1' => 'north'
388     # },
389    
390    
391 elmex 1.1 =head1 AUTHOR
392    
393     Marc Lehmann <schmorp@schmorp.de>
394     http://home.schmorp.de/
395    
396     Robin Redeker <elmex@ta-sa.org>
397     http://www.ta-sa.org/
398    
399     =cut
400     1;
401