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.18 by elmex, Sun Mar 12 23:32:58 2006 UTC vs.
Revision 1.29 by elmex, Mon Mar 20 04:11:41 2006 UTC

13use Crossfire; 13use Crossfire;
14use Crossfire::Map; 14use Crossfire::Map;
15use Crossfire::MapWidget; 15use Crossfire::MapWidget;
16 16
17use GCE::AttrEdit; 17use GCE::AttrEdit;
18use GCE::Util;
18 19
19use Glib::Object::Subclass 20use Glib::Object::Subclass
20 Gtk2::Window; 21 Gtk2::Window;
21 22
22use strict; 23use strict;
59 callback => sub { $self->open_resize_map }, 60 callback => sub { $self->open_resize_map },
60 accelerator => "<ctrl>R" 61 accelerator => "<ctrl>R"
61 }, 62 },
62 ] 63 ]
63 }, 64 },
64 65 _Go => {
66 item_type => '<Branch>',
67 children => [
68 "_Up" => {
69 callback => sub { $self->follow ('u') },
70 accelerator => "<ctrl>U"
71 },
72 "_Down" => {
73 callback => sub { $self->follow ('d') },
74 accelerator => "<ctrl>D"
75 },
76 "_Right" => {
77 callback => sub { $self->follow ('r') },
78 accelerator => "<ctrl>R"
79 },
80 "_Left" => {
81 callback => sub { $self->follow ('l') },
82 accelerator => "<ctrl>L"
83 },
84 ]
85 },
86 _Help => {
87 item_type => '<Branch>',
88 children => [
89 _Help => {
90 callback => sub { $::MAINWIN->show_help_window },
91 accelerator => "<ctrl>H"
92 },
93 ]
94 },
65 ]; 95 ];
66 96
67 my $men = 97 my $men =
68 Gtk2::SimpleMenu->new ( 98 Gtk2::SimpleMenu->new (
69 menu_tree => $menu_tree, 99 menu_tree => $menu_tree,
70 default_callback => \&default_cb, 100 default_callback => \&default_cb,
71 ); 101 );
72 102
103 for (
104 [i => 'pick'],
105 [p => 'place'],
106 [e => 'erase'],
107 [s => 'select'],
108 [l => 'eval'],
109 [x => 'connectexit'],
110 [f => 'followexit']
111 )
112 {
113 my $tool = $_->[1];
114 $men->{accel_group}->connect ($Gtk2::Gdk::Keysyms{$_->[0]}, [], 'visible',
115 sub { $::MAINWIN->set_edit_tool ($tool) });
116 }
117
73 $self->add_accel_group ($men->{accel_group}); 118 $self->add_accel_group ($men->{accel_group});
74 119
75 return $men->{widget}; 120 return $men->{widget};
121}
122
123sub ea {
124 my ($self) = @_;
125 $self->{ea_alt} || $::MAINWIN->{sel_editaction};
76} 126}
77 127
78sub INIT_INSTANCE { 128sub INIT_INSTANCE {
79 my ($self) = @_; 129 my ($self) = @_;
80 130
81 $self->set_title ('gce - map editor'); 131 $self->set_title ('gce - map editor');
82 $self->add (my $vb = Gtk2::VBox->new); 132 $self->add (my $vb = Gtk2::VBox->new);
83 133
84 $self->signal_connect (delete_event => sub { $self->delete }); 134 $self->signal_connect (delete_event => sub { $self->delete; 1 });
85 135
86 $vb->pack_start (my $menu = $self->build_menu, 0, 1, 0); 136 $vb->pack_start (my $menu = $self->build_menu, 0, 1, 0);
87 137
88 $vb->pack_start (my $map = $self->{map} = Crossfire::MapWidget->new, 1, 1, 0); 138 $vb->pack_start (my $map = $self->{map} = Crossfire::MapWidget->new, 1, 1, 0);
89 139
140 $self->signal_connect (focus_in_event => sub {
141 my $ea = $::MAINWIN->{sel_editaction};
142 if ($ea->special_arrow) {
143 $self->{map}->{window}->set_cursor (Gtk2::Gdk::Cursor->new ($ea->special_arrow));
144 } else {
145 $self->{map}->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR'));
146 }
147 delete $self->{ea_alt};
148 });
149
150 $map->signal_connect (key_press_event => sub {
151 my ($map, $event) = @_;
152
153 my $kv = $event->keyval;
154
155 my ($x, $y) = $map->coord ($map->get_pointer);
156 for ([Control_L => sub { $self->{ea_alt} = $::MAINWIN->{edit_collection}{erase} }],
157 [Alt_L => sub { $self->{ea_alt} = $::MAINWIN->{edit_collection}{pick} }],
158 [c => sub { $::MAINWIN->{edit_collection}{select}->copy }],
159 [v => sub { $::MAINWIN->{edit_collection}{select}->paste ($map, $x, $y) }],
160 [n => sub { $::MAINWIN->{edit_collection}{select}->invoke }],
161 )
162 {
163 if ($kv == $Gtk2::Gdk::Keysyms{$_->[0]}) {
164 $_->[1]->();
165 }
166 }
167
168 if ($self->ea->special_arrow) {
169 $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ($self->ea->special_arrow));
170 }
171 1;
172 });
173 $map->signal_connect (key_release_event => sub {
174 my ($map, $event) = @_;
175
176 if ($event->keyval == $Gtk2::Gdk::Keysyms{Control_L}
177 or $event->keyval == $Gtk2::Gdk::Keysyms{Alt_L})
178 {
179 delete $self->{ea_alt};
180 }
181
182 if ($self->ea->special_arrow) {
183 $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ($self->ea->special_arrow));
184 } else {
185 # XXX: Get the original cursor and insert it here
186 $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR'));
187 }
188 1;
189 });
90 $map->signal_connect (button_press_event => sub { 190 $map->signal_connect (button_press_event => sub {
91 my ($map, $event) = @_; 191 my ($map, $event) = @_;
92 192
93 my ($x, $y) = $map->coord ($event->x, $event->y); 193 my ($x, $y) = $map->coord ($event->x, $event->y);
94 my $as = $map->get ($x, $y); 194 my $as = $map->get ($x, $y);
95 195
96 my $btn = $event->button; 196 if ((not $self->{draw_mode}) and $event->button != 2) {
97 197
98 if ((not $self->{draw_mode}) 198 my $ea = $self->ea;
99 and $btn != 2
100 and my $ea = $::MAINWIN->{sel_editaction}) {
101 199
102 $ea->begin ($map, $x, $y, $btn) 200 $ea->begin ($map, $x, $y, $self)
103 if $x >= 0 and $y >= 0 and $x < $map->{map}{width} and $y < $map->{map}{height}; 201 if $x >= 0 and $y >= 0 and $x < $map->{map}{width} and $y < $map->{map}{height};
104 202
105 $self->{draw_mode} = [$ea, $x, $y, $btn]; 203 $self->{draw_mode} = [$x, $y];
106 204
107 $ea->want_cursor 205 $ea->want_cursor
108 or $map->disable_tooltip; 206 or $map->disable_tooltip;
109 207
110 if ($ea->special_arrow) {
111
112 $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ($ea->special_arrow));
113 #'GDK_QUESTION_ARROW'));
114 }
115
116 return 1; 208 return 1;
117 } 209 }
118
119 0 210 0
120 }); 211 });
121 212
122 $map->signal_connect_after (motion_notify_event => sub { 213 $map->signal_connect_after (motion_notify_event => sub {
123 my ($map, $event) = @_; 214 my ($map, $event) = @_;
124 215
125 $self->{draw_mode} 216 $self->{draw_mode}
126 or return; 217 or return;
127 218
219 my $ea = $self->ea;
220
128 my ($X, $Y) = @{$self->{draw_mode}}[1,2]; 221 my ($X, $Y) = @{$self->{draw_mode}}[0,1];
129 my ($x, $y) = $map->coord ($map->get_pointer); 222 my ($x, $y) = $map->coord ($map->get_pointer);
130 223
131 while ($x != $X || $y != $Y) { 224 while ($x != $X || $y != $Y) {
132 225
133 $X++ if $X < $x; 226 $X++ if $X < $x;
134 $X-- if $X > $x; 227 $X-- if $X > $x;
135 $Y++ if $Y < $y; 228 $Y++ if $Y < $y;
136 $Y-- if $Y > $y; 229 $Y-- if $Y > $y;
137 230
138 $self->{draw_mode}[0]->edit ($map, $X, $Y, $self->{draw_mode}[3]) 231 $ea->edit ($map, $X, $Y, $self)
139 if $X >= 0 and $Y >= 0 and $X < $map->{map}{width} and $Y < $map->{map}{height}; 232 if $X >= 0 and $Y >= 0 and $X < $map->{map}{width} and $Y < $map->{map}{height};
140 } 233 }
141 234
142 @{$self->{draw_mode}}[1,2] = ($X, $Y); 235 @{$self->{draw_mode}}[0,1] = ($X, $Y);
143 236
144 1 237 1
145 }); 238 });
146 239
147 $map->signal_connect (button_release_event => sub { 240 $map->signal_connect (button_release_event => sub {
148 my ($map, $event) = @_; 241 my ($map, $event) = @_;
149 242
150 if ($self->{draw_mode} 243 if ($self->{draw_mode}) {
151 and my $ea = $self->{draw_mode}[0]
152 and $self->{draw_mode}[3] == $event->button) {
153
154 my ($x, $y) = $map->coord ($map->get_pointer); 244 my ($x, $y) = $map->coord ($map->get_pointer);
155 245
246 my $ea = $self->ea;
156 $ea->end ($map, $x, $y, $event->button); 247 $ea->end ($map, $x, $y, $self);
157
158 if ($ea->special_arrow) {
159
160 # XXX: Get the original cursor and insert it here
161 $map->{window}->set_cursor (Gtk2::Gdk::Cursor->new ('GDK_LEFT_PTR'));
162 }
163 248
164 delete $self->{draw_mode}; 249 delete $self->{draw_mode};
165 250
166 $ea->want_cursor 251 $ea->want_cursor
167 or $map->enable_tooltip; 252 or $map->enable_tooltip;
195 or return; 280 or return;
196 281
197 $map->change_swap ($map->{undo_stack}[$map->{undo_stack_pos}++]); 282 $map->change_swap ($map->{undo_stack}[$map->{undo_stack_pos}++]);
198} 283}
199 284
200sub delete_arch {
201 my ($self, $x, $y) = @_;
202
203 defined $self->{map}
204 or return 0;
205
206 my $as = $self->{map}->get ($x, $y);
207 pop @$as;
208 $self->{map}->set ($x, $y, $as);
209}
210
211sub place_pick {
212 my ($self, $x, $y) = @_;
213
214 my $pick = $::MAINWIN->get_pick;
215 my $as = $self->{map}->get ($x, $y);
216
217 my $arch = { _name => $pick->{_name} };
218
219 push @$as, $arch
220 unless @$as && $as->[-1]->{_name} eq $arch->{_name};
221
222 $self->{map}->set ($x, $y, $as);
223}
224
225sub delete { 285sub delete {
226 my ($self) = @_; 286 my ($self) = @_;
227 287
228 # check and modla dialog if "dirty" 288 # check and modla dialog if "dirty"
229 289
290 if ($self->{mapkey}) {
291 # XXX: This should be in a delete event handler in the MainWindow.pm... but it doesnt work
292 delete $::MAINWIN->{loaded_maps}->{$self->{mapkey}};
293 }
294
230 $self->destroy; 295 $self->destroy;
231} 296}
232 297
233sub open_map { 298sub open_map {
234 my ($self, $path) = @_; 299 my ($self, $path, $key) = @_;
300
301 $self->{mapkey} = $key;
235 302
236 if (ref $path) { 303 if (ref $path) {
237 print "REFE\n";
238 $self->{map}->set_map ($path); 304 $self->{map}->set_map ($path);
239 print "UNREF\n";
240 305
241 } else { 306 } else {
242 $self->{path} = $path; 307 $self->{path} = $path;
243# print "OPENMAP $path\n"; 308# print "OPENMAP $path\n";
244 $self->{map}->set_map (my $m = new_from_file Crossfire::Map $path); 309 $self->{map}->set_map (my $m = new_from_file Crossfire::Map $path);
248} 313}
249 314
250sub save_map { 315sub save_map {
251 my ($self) = @_; 316 my ($self) = @_;
252 317
318 if ($self->{path}) {
253 $self->{map}{map}->write_file ($self->{path}); 319 $self->{map}{map}->write_file ($self->{path});
320 quick_msg ($self, "saved to $self->{path}");
321 } else {
322 $self->save_map_as;
323 }
254} 324}
255 325
256sub save_map_as { 326sub save_map_as {
257 my ($self) = @_; 327 my ($self) = @_;
258 warn "save_map_as nyi\n"; 328
329 my $fc = $::MAINWIN->new_filechooser ('gce - save map', 1, $self->{path});
330
331 if ('ok' eq $fc->run) {
332
333 $::MAINWIN->{fc_last_folder} = $fc->get_current_folder;
334 $::MAINWIN->{fc_last_folders}->{$self->{fc_last_folder}}++;
335
336 $self->{map}{map}->write_file ($self->{path} = $fc->get_filename);
337 quick_msg ($self, "saved to $self->{path}");
338 }
339
340 $fc->destroy;
259} 341}
260 342
261sub _add_prop_entry { 343sub _add_prop_entry {
262 my ($self, $table, $idx, $key, $desc, $type, $changecb) = @_; 344 my ($self, $table, $idx, $key, $desc, $type, $changecb) = @_;
263
264 345
265 my $edwid; 346 my $edwid;
266 347
267 if ($type eq 'string') { 348 if ($type eq 'string') {
268 $table->attach_defaults (my $lbl = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1); 349 $table->attach_defaults (my $lbl = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1);
269 $edwid = Gtk2::Entry->new; 350 $edwid = Gtk2::Entry->new;
270 $edwid->set_text ($self->{map}{map}{info}{$key}); 351 $edwid->set_text ($self->{map}{map}{info}{$key});
271 $edwid->signal_connect (changed => sub { 352 $edwid->signal_connect (changed => sub {
272 $self->{map}{map}{info}{$key} = $_[0]->get_text; 353 $self->{map}{map}{info}{$key} = $_[0]->get_text;
273 if ($changecb) { 354 if ($changecb) {
274 print "CHANGECB " . $_[0]->get_text . "\n";
275 $changecb->($_[0]->get_text); 355 $changecb->($_[0]->get_text);
276 } 356 }
277 }); 357 });
278 $table->attach_defaults ($edwid, 1, 2, $idx, $idx + 1); 358 $table->attach_defaults ($edwid, 1, 2, $idx, $idx + 1);
279 359
284 } elsif ($type eq 'label') { 364 } elsif ($type eq 'label') {
285 $table->attach_defaults (my $lbl = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1); 365 $table->attach_defaults (my $lbl = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1);
286 $edwid = Gtk2::Label->new ($self->{map}{map}{info}{$key}); 366 $edwid = Gtk2::Label->new ($self->{map}{map}{info}{$key});
287 $table->attach_defaults ($edwid, 1, 2, $idx, $idx + 1); 367 $table->attach_defaults ($edwid, 1, 2, $idx, $idx + 1);
288 368
369 } elsif ($type eq 'check') {
370 $table->attach_defaults (my $lbl1 = Gtk2::Label->new ($desc), 0, 1, $idx, $idx + 1);
371 $table->attach_defaults (my $lbl = Gtk2::CheckButton->new, 1, 2, $idx, $idx + 1);
372 $lbl->set_active ($self->{map}{map}{info}{$key});
373 $lbl->signal_connect (toggled => sub {
374 my ($lbl) = @_;
375 $self->{map}{map}{info}{$key} = $lbl->get_active * 1;
376 ($changecb || sub {})->($lbl->get_active);
377 });
378
379 } elsif ($type eq 'sep') {
380 $table->attach_defaults (my $lbl1 = Gtk2::HSeparator->new, 0, 2, $idx, $idx + 1);
289 } else { 381 } else {
290 $edwid = Gtk2::Label->new ("FOO"); 382 $edwid = Gtk2::Label->new ("FOO");
291 } 383 }
292} 384}
293 385
306 [qw/width Width string/], 398 [qw/width Width string/],
307 [qw/height Height string/], 399 [qw/height Height string/],
308 [qw/save Save button/, 400 [qw/save Save button/,
309 sub { 401 sub {
310 $self->{map}{map}->resize ($self->{map}{map}{info}{width}, $self->{map}{map}{info}{height}); 402 $self->{map}{map}->resize ($self->{map}{map}{info}{width}, $self->{map}{map}{info}{height});
311 $self->{map}->invalidate_all 403 $self->{map}->invalidate_all;
404 $w->destroy;
312 } 405 }
313 ], 406 ],
314 ) 407 )
315 { 408 {
316 $self->_add_prop_entry ($t, $i++, @$_); 409 $self->_add_prop_entry ($t, $i++, @$_);
317 } 410 }
318 411
319 $w->show_all; 412 $w->show_all;
413}
414
415sub follow {
416 my ($self, $dir) = @_;
417
418 my %dir_to_path = (
419 u => 'tile_path_1',
420 d => 'tile_path_3',
421 r => 'tile_path_2',
422 l => 'tile_path_4',
423 );
424
425 defined $dir_to_path{$dir}
426 or return;
427 my $map = $self->{map}{map}{info}{$dir_to_path{$dir}}
428 or return;
429
430 $map = map2abs ($map, $self);
431 $::MAINWIN->open_map_editor ($map);
320} 432}
321 433
322sub open_map_prop { 434sub open_map_prop {
323 my ($self) = @_; 435 my ($self) = @_;
324 436
330 $sw->set_policy ('automatic', 'automatic'); 442 $sw->set_policy ('automatic', 'automatic');
331 $v->pack_start (my $t = Gtk2::Table->new (2, 10), 0, 0, 0); 443 $v->pack_start (my $t = Gtk2::Table->new (2, 10), 0, 0, 0);
332 444
333 my $i = 0; 445 my $i = 0;
334 for ( 446 for (
335 [qw/name Name string/], 447 [qw/name Name string/],
336 [qw/region Region string/], 448 [qw/region Region string/],
449 [qw/enter_x Enter-x string/],
450 [qw/enter_y Enter-y string/],
451 [qw/reset_timeout Reset-timeout string/],
452 [qw/swap_time Swap-timeout string/],
453 [qw/x x sep/],
337 [qw/difficulty Difficulty string/], 454 [qw/difficulty Difficulty string/],
455 [qw/windspeed Windspeed string/],
456 [qw/pressure Pressure string/],
457 [qw/humid Humid string/],
458 [qw/temp Temp string/],
459 [qw/darkness Darkness string/],
460 [qw/sky Sky string/],
461 [qw/winddir Winddir string/],
462 [qw/x x sep/],
338 [qw/width Width label/], # sub { $self->{map}{map}->resize ($_[0], $self->{map}{map}{height}) }], 463 [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]) }], 464 [qw/height Height label/], # sub { $self->{map}{map}->resize ($self->{map}{map}{width}, $_[0]) }],
465 [qw/x x sep/],
340 [qw/msg Text text/], 466 [qw/msg Text text/],
467 [qw/maplore Maplore text/],
468 [qw/outdoor Outdoor check/],
469 [qw/unique Unique check/],
470 [qw/fixed_resettime Fixed-resettime check/],
471 [qw/x x sep/],
341 [qw/tile_path_1 Northpath string/], 472 [qw/tile_path_1 Northpath string/],
342 [qw/tile_path_2 Eastpath string/], 473 [qw/tile_path_2 Eastpath string/],
343 [qw/tile_path_3 Southpath string/], 474 [qw/tile_path_3 Southpath string/],
344 [qw/tile_path_4 Westpath string/], 475 [qw/tile_path_4 Westpath string/],
345 [qw/tile_path_5 Toppath string/], 476 [qw/tile_path_5 Toppath string/],
346 [qw/tile_path_6 Bottompath string/], 477 [qw/tile_path_6 Bottompath string/],
347 ) 478 )
348 { 479 {
349 $self->_add_prop_entry ($t, $i++, @$_); 480 $self->_add_prop_entry ($t, $i++, @$_);
350 } 481 }
351 482
352 $w->show_all; 483 $w->show_all;
353} 484}
354 485
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=head1 AUTHOR 486=head1 AUTHOR
392 487
393 Marc Lehmann <schmorp@schmorp.de> 488 Marc Lehmann <schmorp@schmorp.de>
394 http://home.schmorp.de/ 489 http://home.schmorp.de/
395 490

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines