… | |
… | |
21 | bless $self, $class; |
21 | bless $self, $class; |
22 | $self->init; |
22 | $self->init; |
23 | return $self; |
23 | return $self; |
24 | } |
24 | } |
25 | |
25 | |
26 | |
26 | sub tool_widget { if ($_[1]) { $_[0]->{widget} = $_[1] } $_[0]->{widget} } |
27 | sub tool_widget { } |
|
|
28 | sub init { } |
27 | sub init { } |
29 | |
28 | |
30 | sub want_cursor { 1 } |
29 | sub want_cursor { 1 } |
31 | |
30 | |
32 | sub special_arrow { } |
31 | sub special_arrow { } |
… | |
… | |
63 | |
62 | |
64 | #TODO: limit undo stack size to some preconfigured limit |
63 | #TODO: limit undo stack size to some preconfigured limit |
65 | } |
64 | } |
66 | } |
65 | } |
67 | |
66 | |
|
|
67 | package GCE::EditAction::RadioModed; |
|
|
68 | |
|
|
69 | our @ISA = qw/GCE::EditAction/; |
|
|
70 | |
|
|
71 | sub add_mode_button { |
|
|
72 | my ($self, $vb, $lbl, $mode, $default) = @_; |
|
|
73 | |
|
|
74 | $vb->pack_start (my $b = Gtk2::RadioButton->new ($self->{place_radio_grp}, $lbl), 0, 1, 0); |
|
|
75 | unless (defined $self->{place_radio_grp}) { |
|
|
76 | $self->{place_radio_grp} = $b->get_group; |
|
|
77 | |
|
|
78 | unless (defined $default) { |
|
|
79 | $b->set_active (1); |
|
|
80 | $self->set_mode ($mode); |
|
|
81 | } |
|
|
82 | } |
|
|
83 | if ($default) { |
|
|
84 | $b->set_active (1); |
|
|
85 | $self->set_mode ($mode); |
|
|
86 | } |
|
|
87 | $b->signal_connect (clicked => sub { |
|
|
88 | $self->set_mode ($mode); |
|
|
89 | }); |
|
|
90 | } |
|
|
91 | |
|
|
92 | sub set_mode { |
|
|
93 | my ($self, $mode) = @_; |
|
|
94 | $self->{place_mode} = $mode; |
|
|
95 | } |
|
|
96 | |
|
|
97 | sub get_mode { |
|
|
98 | my ($self) = @_; |
|
|
99 | $self->{place_mode} |
|
|
100 | } |
|
|
101 | |
|
|
102 | sub init { |
|
|
103 | my ($self) = @_; |
|
|
104 | |
|
|
105 | die "Implement me!!"; |
|
|
106 | |
|
|
107 | # my $vb = new Gtk2::VBox; |
|
|
108 | # $self->_add_mode_button ($vb, "auto", "auto"); |
|
|
109 | # $self->_add_mode_button ($vb, "top", "top"); |
|
|
110 | # $self->_add_mode_button ($vb, "above floor", "above"); |
|
|
111 | # $self->_add_mode_button ($vb, "below floor", "below"); |
|
|
112 | # $self->_add_mode_button ($vb, "bottom", "bottom"); |
|
|
113 | # |
|
|
114 | # $self->{widget} = $vb; |
|
|
115 | } |
68 | |
116 | |
69 | package GCE::EditAction::Pick; |
117 | package GCE::EditAction::Pick; |
|
|
118 | use strict; |
70 | |
119 | |
71 | our @ISA = qw/GCE::EditAction/; |
120 | our @ISA = qw/GCE::EditAction/; |
|
|
121 | |
|
|
122 | sub want_cursor { 0 } |
72 | |
123 | |
73 | sub special_arrow { 'GDK_HAND2' } |
124 | sub special_arrow { 'GDK_HAND2' } |
74 | |
125 | |
75 | sub begin { |
126 | sub begin { |
76 | my ($self, $map, $x, $y, $btn) = @_; |
127 | my ($self, $map, $x, $y, $btn) = @_; |
… | |
… | |
112 | |
163 | |
113 | use GCE::Util; |
164 | use GCE::Util; |
114 | use Gtk2; |
165 | use Gtk2; |
115 | use strict; |
166 | use strict; |
116 | |
167 | |
117 | our @ISA = qw/GCE::EditAction/; |
168 | our @ISA = qw/GCE::EditAction::RadioModed/; |
118 | |
|
|
119 | sub _add_mode_button { |
|
|
120 | my ($self, $vb, $lbl, $mode) = @_; |
|
|
121 | |
|
|
122 | $vb->pack_start (my $b = Gtk2::RadioButton->new ($self->{place_radio_grp}, $lbl), 0, 1, 0); |
|
|
123 | unless (defined $self->{place_radio_grp}) { |
|
|
124 | $self->{place_radio_grp} = $b->get_group; |
|
|
125 | $b->set_active (1); |
|
|
126 | $self->set_place_mode ($mode); |
|
|
127 | } |
|
|
128 | $b->signal_connect (clicked => sub { |
|
|
129 | $self->set_place_mode ($mode); |
|
|
130 | }); |
|
|
131 | } |
|
|
132 | |
|
|
133 | sub set_place_mode { |
|
|
134 | my ($self, $mode) = @_; |
|
|
135 | $self->{place_mode} = $mode; |
|
|
136 | } |
|
|
137 | |
169 | |
138 | sub init { |
170 | sub init { |
139 | my ($self) = @_; |
171 | my ($self) = @_; |
140 | |
172 | |
141 | my $vb = new Gtk2::VBox; |
173 | my $vb = new Gtk2::VBox; |
142 | $self->_add_mode_button ($vb, "auto", "auto"); |
174 | $self->add_mode_button ($vb, "auto", "auto"); |
143 | $self->_add_mode_button ($vb, "top", "top"); |
175 | $self->add_mode_button ($vb, "top", "top"); |
144 | $self->_add_mode_button ($vb, "above floor", "above"); |
176 | $self->add_mode_button ($vb, "above floor", "above"); |
145 | $self->_add_mode_button ($vb, "below floor", "below"); |
177 | $self->add_mode_button ($vb, "below floor", "below"); |
146 | $self->_add_mode_button ($vb, "bottom", "bottom"); |
178 | $self->add_mode_button ($vb, "bottom", "bottom"); |
147 | |
179 | |
148 | $self->{widget} = $vb; |
180 | $self->tool_widget ($vb); |
149 | } |
|
|
150 | |
|
|
151 | sub tool_widget { |
|
|
152 | my ($self) = @_; |
|
|
153 | return $self->{widget}; |
|
|
154 | } |
181 | } |
155 | |
182 | |
156 | sub want_cursor { 0 } |
183 | sub want_cursor { 0 } |
157 | |
184 | |
158 | sub begin { |
185 | sub begin { |
… | |
… | |
193 | } |
220 | } |
194 | |
221 | |
195 | sub stack_action { |
222 | sub stack_action { |
196 | my ($self, $stack, $arch) = @_; |
223 | my ($self, $stack, $arch) = @_; |
197 | |
224 | |
198 | my $m = $self->{place_mode}; |
225 | my $m = $self->get_mode; |
199 | |
226 | |
200 | if ($m eq 'top') { |
227 | if ($m eq 'top') { |
201 | if (@$stack == 0 or $stack->[-1]->{_name} ne $arch->{_name}) { |
228 | if (@$stack == 0 or $stack->[-1]->{_name} ne $arch->{_name}) { |
202 | push @$stack, $arch; |
229 | push @$stack, $arch; |
203 | } |
230 | } |
… | |
… | |
267 | } |
294 | } |
268 | } |
295 | } |
269 | } |
296 | } |
270 | |
297 | |
271 | package GCE::EditAction::Erase; |
298 | package GCE::EditAction::Erase; |
|
|
299 | use GCE::Util; |
|
|
300 | use Gtk2; |
|
|
301 | use strict; |
272 | |
302 | |
273 | our @ISA = qw/GCE::EditAction/; |
303 | our @ISA = qw/GCE::EditAction::RadioModed/; |
274 | |
304 | |
275 | sub want_cursor { 0 } |
305 | sub want_cursor { 0 } |
|
|
306 | |
|
|
307 | sub init { |
|
|
308 | my ($self) = @_; |
|
|
309 | |
|
|
310 | my $vb = new Gtk2::VBox; |
|
|
311 | $self->add_mode_button ($vb, "top", "top"); |
|
|
312 | $self->add_mode_button ($vb, "walls", "walls"); |
|
|
313 | $self->add_mode_button ($vb, "above floor", "above", 'default'); |
|
|
314 | $self->add_mode_button ($vb, "floor", "floor"); |
|
|
315 | $self->add_mode_button ($vb, "below floor", "below"); |
|
|
316 | $self->add_mode_button ($vb, "bottom", "bottom"); |
|
|
317 | $self->add_mode_button ($vb, "pick match", "match"); |
|
|
318 | |
|
|
319 | $self->tool_widget ($vb); |
|
|
320 | |
|
|
321 | $vb->pack_start ($self->{no_wall_check} = Gtk2::CheckButton->new ("exclude walls"), 0, 1, 0); |
|
|
322 | $vb->pack_start ($self->{no_monsters_check} = Gtk2::CheckButton->new ("exclude monsters"), 0, 1, 0); |
|
|
323 | } |
|
|
324 | |
|
|
325 | sub check_excluded { |
|
|
326 | my ($self, $arch) = @_; |
|
|
327 | |
|
|
328 | my $a1 = $self->{no_monsters_check}->get_active; |
|
|
329 | my $a2 = $self->{no_wall_check}->get_active; |
|
|
330 | |
|
|
331 | my $r = ($self->{no_wall_check}->get_active && arch_is_wall ($arch)) |
|
|
332 | || ($self->{no_monsters_check}->get_active && arch_is_monster ($arch)); |
|
|
333 | return $r; |
|
|
334 | } |
276 | |
335 | |
277 | sub begin { |
336 | sub begin { |
278 | my ($self, $map, $x, $y, $btn) = @_; |
337 | my ($self, $map, $x, $y, $btn) = @_; |
279 | |
338 | |
280 | $self->SUPER::begin ($map, $x, $y, $btn); |
339 | $self->SUPER::begin ($map, $x, $y, $btn); |
… | |
… | |
283 | |
342 | |
284 | sub edit { |
343 | sub edit { |
285 | my ($self, $map, $x, $y, $btn) = @_; |
344 | my ($self, $map, $x, $y, $btn) = @_; |
286 | |
345 | |
287 | my $as = $map->get ($x, $y); |
346 | my $as = $map->get ($x, $y); |
288 | pop @$as; |
347 | $self->stack_action ($as); |
289 | $map->change_stack ($x, $y, $as); |
348 | $map->change_stack ($x, $y, $as); |
290 | } |
349 | } |
|
|
350 | |
|
|
351 | sub stack_action { |
|
|
352 | my ($self, $stack) = @_; |
|
|
353 | |
|
|
354 | my $m = $self->get_mode; |
|
|
355 | |
|
|
356 | if ($m eq 'top') { |
|
|
357 | pop @$stack; |
|
|
358 | |
|
|
359 | } elsif ($m eq 'bottom') { |
|
|
360 | shift @$stack; |
|
|
361 | |
|
|
362 | } elsif ($m eq 'above') { |
|
|
363 | my $fidx = stack_find_floor ($stack, 'from_top'); |
|
|
364 | |
|
|
365 | if (arch_is_floor ($stack->[$fidx]) and $stack->[$fidx + 1]) { |
|
|
366 | splice (@$stack, $fidx + 1, 1) |
|
|
367 | unless $self->check_excluded ($stack->[$fidx + 1]) |
|
|
368 | |
|
|
369 | } elsif (not arch_is_floor ($stack->[$fidx])) { |
|
|
370 | splice (@$stack, $fidx, 1) |
|
|
371 | unless $self->check_excluded ($stack->[$fidx]) |
|
|
372 | |
|
|
373 | } |
|
|
374 | |
|
|
375 | } elsif ($m eq 'below') { |
|
|
376 | my $fidx = stack_find_floor ($stack, 'from_bottom'); |
|
|
377 | |
|
|
378 | if ($fidx > 0 and not arch_is_floor ($stack->[$fidx - 1])) { |
|
|
379 | splice (@$stack, $fidx - 1, 1) |
|
|
380 | unless $self->check_excluded ($stack->[$fidx - 1]) |
|
|
381 | |
|
|
382 | } elsif (not arch_is_floor ($stack->[$fidx])) { # no floor found |
|
|
383 | splice (@$stack, $fidx, 1) |
|
|
384 | unless $self->check_excluded ($stack->[$fidx]) |
|
|
385 | |
|
|
386 | } |
|
|
387 | |
|
|
388 | } elsif ($m eq 'walls') { |
|
|
389 | my $widx = stack_find_wall ($stack, 'from_top'); |
|
|
390 | |
|
|
391 | while (arch_is_wall ($stack->[$widx])) { |
|
|
392 | splice (@$stack, $widx, 1); |
|
|
393 | $widx = stack_find_wall ($stack, 'from_top') |
|
|
394 | } |
|
|
395 | |
|
|
396 | } elsif ($m eq 'floor') { |
|
|
397 | my $fidx = stack_find_floor ($stack, 'from_top'); |
|
|
398 | |
|
|
399 | while (arch_is_floor ($stack->[$fidx])) { |
|
|
400 | splice (@$stack, $fidx, 1); |
|
|
401 | $fidx = stack_find_floor ($stack, 'from_top') |
|
|
402 | } |
|
|
403 | |
|
|
404 | } elsif ($m eq 'match') { |
|
|
405 | my $pick_name = $::MAINWIN->get_pick ()->{_name}; |
|
|
406 | my $idx = stack_find ($stack, 'from_top', sub { $_[0]->{_name} eq $pick_name }); |
|
|
407 | |
|
|
408 | while ($stack->[$idx] and $stack->[$idx]->{_name} eq $pick_name) { |
|
|
409 | splice (@$stack, $idx, 1); |
|
|
410 | $idx = stack_find ($stack, 'from_top', sub { $_[0]->{_name} eq $pick_name }); |
|
|
411 | } |
|
|
412 | } |
|
|
413 | } |
|
|
414 | |
|
|
415 | |
291 | |
416 | |
292 | =head1 AUTHOR |
417 | =head1 AUTHOR |
293 | |
418 | |
294 | Marc Lehmann <schmorp@schmorp.de> |
419 | Marc Lehmann <schmorp@schmorp.de> |
295 | http://home.schmorp.de/ |
420 | http://home.schmorp.de/ |