ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/MapEditor.pm
(Generate patch)

Comparing deliantra/gde/GCE/MapEditor.pm (file contents):
Revision 1.6 by elmex, Mon Feb 20 13:30:28 2006 UTC vs.
Revision 1.21 by elmex, Thu Mar 16 01:13:57 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines