ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/gde/GCE/EditAction.pm
Revision: 1.6
Committed: Fri Mar 10 20:32:47 2006 UTC (18 years, 2 months ago) by elmex
Branch: MAIN
Changes since 1.5: +126 -1 lines
Log Message:
implemented edit tools widgets and improved the placement tool

File Contents

# User Rev Content
1 elmex 1.1 package GCE::EditAction;
2    
3     =head1 NAME
4    
5     GCE::EditActions - this is the abstraction of edit actions (placing, deleting, etc.)
6    
7     =cut
8    
9     use Gtk2;
10     use Gtk2::Gdk::Keysyms;
11     use Gtk2::SimpleMenu;
12    
13     use Crossfire;
14     use Crossfire::MapWidget;
15    
16     use strict;
17    
18     sub new {
19     my $class = shift;
20     my $self = { @_ };
21     bless $self, $class;
22 elmex 1.6 $self->init;
23 elmex 1.1 return $self;
24     }
25    
26 elmex 1.6
27     sub tool_widget { }
28     sub init { }
29    
30 elmex 1.1 sub want_cursor { 1 }
31    
32     sub special_arrow { }
33    
34     # edits one tile of the map
35     sub edit_one {
36     my ($self, $x, $y) = @_;
37     # do one edition
38     }
39    
40     # edits a selection
41     sub edit_selection {
42     }
43    
44     # abstraction for edit_one and edit_selection ?
45     # takes selection if present
46     sub edit {
47     my ($self, $map, $x, $y, $btn) = @_;
48     }
49    
50     sub begin {
51     my ($self, $map, $x, $y, $btn) = @_;
52 root 1.3
53     $map->change_begin (ref $self);
54 elmex 1.1 }
55 root 1.3
56 elmex 1.1 sub end {
57 root 1.3 my ($self, $map) = @_;
58    
59     if (my $changeset = $map->change_end) {
60     splice @{ $map->{undo_stack} ||= [] },
61 root 1.4 $map->{undo_stack_pos}++, 1e6,
62 root 1.3 $changeset;
63    
64     #TODO: limit undo stack size to some preconfigured limit
65     }
66 elmex 1.1 }
67    
68    
69     package GCE::EditAction::Pick;
70    
71     our @ISA = qw/GCE::EditAction/;
72    
73     sub special_arrow { 'GDK_HAND2' }
74    
75     sub begin {
76     my ($self, $map, $x, $y, $btn) = @_;
77    
78 root 1.3 $self->SUPER::begin ($map, $x, $y, $btn);
79 elmex 1.1 $self->edit ($map, $x, $y, $btn);
80     }
81    
82     sub edit {
83     my ($self, $map, $x, $y, $btn) = @_;
84    
85     my $cstack = $map->get ($x, $y);
86    
87     my $arch = $cstack->[-1];
88    
89     # virtual... grmbl....
90     # FIXME: I have to patch the stack of the real arch??? argl.. how??
91     if ($arch->{_virtual}) {
92 root 1.3 $x = $arch->{virtual_x};
93     $y = $arch->{virtual_y};
94 elmex 1.1 $arch = $arch->{_virtual};
95 elmex 1.6 $cstack = $map->get ($x, $y);
96 elmex 1.1 }
97    
98 root 1.5 $::MAINWIN->set_pick ($arch)
99 root 1.3 if @$cstack && $btn == 1;
100 elmex 1.1
101 root 1.5 $::MAINWIN->update_attr_editor ($arch, sub {
102 elmex 1.6 my ($arch) = @_;
103     print "UPD: $arch\n"; #d#
104    
105 root 1.3 $map->change_stack ($x, $y, $cstack);
106 elmex 1.1 });
107    
108 root 1.5 $::MAINWIN->update_stack_view ($map, $x, $y);
109 elmex 1.1 }
110    
111     package GCE::EditAction::Place;
112    
113 elmex 1.2 use GCE::Util;
114 elmex 1.6 use Gtk2;
115     use strict;
116 elmex 1.2
117 elmex 1.1 our @ISA = qw/GCE::EditAction/;
118    
119 elmex 1.6 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    
138     sub init {
139     my ($self) = @_;
140    
141     my $vb = new Gtk2::VBox;
142     $self->_add_mode_button ($vb, "auto", "auto");
143     $self->_add_mode_button ($vb, "top", "top");
144     $self->_add_mode_button ($vb, "above floor", "above");
145     $self->_add_mode_button ($vb, "below floor", "below");
146     $self->_add_mode_button ($vb, "bottom", "bottom");
147    
148     $self->{widget} = $vb;
149     }
150    
151     sub tool_widget {
152     my ($self) = @_;
153     return $self->{widget};
154     }
155    
156 elmex 1.1 sub want_cursor { 0 }
157    
158     sub begin {
159     my ($self, $map, $x, $y, $btn) = @_;
160    
161 root 1.3 $self->SUPER::begin ($map, $x, $y, $btn);
162 elmex 1.1 $self->edit ($map, $x, $y, $btn);
163     }
164    
165     sub edit {
166     my ($self, $map, $x, $y, $btn) = @_;
167    
168     if ($btn == 3) { # btn 3 does pick
169    
170     my $cstack = $map->get ($x, $y) or return;
171 root 1.3 my $arch = $cstack->[-1];
172 elmex 1.1
173     $arch->{_virtual}
174     and $arch = $arch->{_virtual};
175    
176 root 1.5 $::MAINWIN->set_pick ($arch)
177 elmex 1.1 if @$cstack;;
178    
179     } else {
180    
181 root 1.5 my $pick = $::MAINWIN->get_pick;
182 elmex 1.1 my $as = $map->get ($x, $y);
183    
184     my $arch = { _name => $pick->{_name} };
185    
186 elmex 1.6 $self->stack_action ($as, $arch);
187     $map->change_stack ($x, $y, $as); # insert_arch_stack_layer ($as, $arch));
188 elmex 1.2 # push @$as, $arch
189     # unless @$as && $as->[-1]->{_name} eq $arch->{_name};
190 elmex 1.1
191 elmex 1.2 #$map->set ($x, $y, $as);
192 elmex 1.1 }
193     }
194    
195 elmex 1.6 sub stack_action {
196     my ($self, $stack, $arch) = @_;
197    
198     my $m = $self->{place_mode};
199    
200     if ($m eq 'top') {
201     if (@$stack == 0 or $stack->[-1]->{_name} ne $arch->{_name}) {
202     push @$stack, $arch;
203     }
204    
205     } elsif ($m eq 'bottom') {
206     if (@$stack == 0 or $stack->[0]->{_name} ne $arch->{_name}) {
207     unshift @$stack, $arch;
208     }
209    
210     } elsif ($m eq 'above') {
211     my $fidx = stack_find_floor ($stack, 'from_top');
212    
213     if (@$stack == 0
214     or not ($stack->[$fidx + 1])
215     or $stack->[$fidx + 1]->{_name} ne $arch->{_name})
216     {
217     splice (@$stack, $fidx + 1, 0, $arch);
218     }
219    
220     } elsif ($m eq 'below') {
221     my $fidx = stack_find_floor ($stack, 'from_bottom');
222    
223     if (@$stack == 0
224     or $fidx == 0
225     or not ($stack->[$fidx - 1])
226     or $stack->[$fidx - 1]->{_name} ne $arch->{_name})
227     {
228     splice (@$stack, $fidx, 0, $arch);
229     }
230    
231     } elsif ($m eq 'auto') {
232     my $fidx = stack_find_floor ($stack, 'from_top');
233     my $widx = stack_find_wall ($stack);
234    
235     if (arch_is_floor ($arch)) { # we want to place a floor tile
236    
237     if (arch_is_floor ($stack->[$fidx])) { # replace
238     $stack->[$fidx] = $arch;
239    
240     } else { # insert on bottom
241     unshift @$stack, $arch;
242     }
243    
244     } elsif (arch_is_wall ($arch)) { # we want to place a wall
245    
246     if (arch_is_wall ($stack->[$widx])) { # replace
247     $stack->[$widx] = $arch;
248    
249     } else { # insert above floor
250     splice (@$stack, $fidx + 1, 0, $arch);
251     }
252    
253     } else {
254    
255     if (arch_is_wall ($stack->[$widx])) {
256     # if we have a wall above the floor, we don't want to place anything
257     # on that tile anymore
258     return;
259     }
260    
261     if (@$stack == 0
262     or not ($stack->[-1])
263     or $stack->[-1]->{_name} ne $arch->{_name})
264     {
265     push @$stack, $arch;
266     }
267     }
268     }
269     }
270    
271 elmex 1.1 package GCE::EditAction::Erase;
272    
273     our @ISA = qw/GCE::EditAction/;
274    
275     sub want_cursor { 0 }
276    
277     sub begin {
278     my ($self, $map, $x, $y, $btn) = @_;
279    
280 root 1.3 $self->SUPER::begin ($map, $x, $y, $btn);
281 elmex 1.1 $self->edit ($map, $x, $y, $btn);
282     }
283    
284     sub edit {
285     my ($self, $map, $x, $y, $btn) = @_;
286    
287     my $as = $map->get ($x, $y);
288     pop @$as;
289 root 1.3 $map->change_stack ($x, $y, $as);
290 elmex 1.1 }
291    
292     =head1 AUTHOR
293    
294     Marc Lehmann <schmorp@schmorp.de>
295     http://home.schmorp.de/
296    
297     Robin Redeker <elmex@ta-sa.org>
298     http://www.ta-sa.org/
299    
300     =cut
301 root 1.5
302     1
303 elmex 1.1