… | |
… | |
21 | update_stack_view => { return_type => undef, param_types => [Glib::Int, Glib::Int, Glib::Scalar] }, |
21 | update_stack_view => { return_type => undef, param_types => [Glib::Int, Glib::Int, Glib::Scalar] }, |
22 | }; |
22 | }; |
23 | |
23 | |
24 | use strict; |
24 | use strict; |
25 | |
25 | |
26 | sub get_tile_stack { |
26 | |
|
|
27 | sub delete_arch { |
27 | my ($self, $x, $y) = @_; |
28 | my ($self, $x, $y) = @_; |
28 | my $as; |
|
|
29 | |
29 | |
30 | if ($x > 0 || $x < $self->{map}{width} |
30 | return 0 unless |
31 | || $y > 0 || $y < $self->{map}{height}) { |
31 | defined $self->{map}; |
32 | |
32 | |
33 | $as = $self->{map}{map}{map}[$x][$y] || []; |
33 | my ($mx, $my) = $self->{map}->coord ($x, $y); |
|
|
34 | my $s = map_pop_tile_stack ($self->{map}, $mx, $my); |
|
|
35 | $self->{map}->update_map ($mx, $my, 1, 1); |
|
|
36 | } |
|
|
37 | |
|
|
38 | |
|
|
39 | sub get_top_arch { |
|
|
40 | my ($self, $x, $y) = @_; |
|
|
41 | |
|
|
42 | return 0 unless |
|
|
43 | defined $self->{map}; |
|
|
44 | |
|
|
45 | map_get_tile_stack ($self->{map}, $self->{map}->coord ($x, $y))->[-1] |
|
|
46 | } |
|
|
47 | |
|
|
48 | sub place_pick { |
|
|
49 | my ($self, $x, $y) = @_; |
|
|
50 | |
|
|
51 | return 0 unless |
|
|
52 | defined $self->{map} |
|
|
53 | and defined $self->{pick_arch}; |
|
|
54 | |
|
|
55 | my ($mx, $my) = $self->{map}->coord ($x, $y); |
|
|
56 | my $s = map_get_tile_stack ($self->{map}, $mx, $my); |
|
|
57 | my $top = $s->[-1]; |
|
|
58 | my $arch = { _name => $self->{pick_arch}->{_name} }; |
|
|
59 | |
|
|
60 | if ($top->{_name} ne $arch->{_name}) { |
|
|
61 | map_push_tile_stack ($self->{map}, $mx, $my, $arch); |
34 | } |
62 | } |
35 | |
63 | |
36 | return $as; |
64 | $self->{map}->update_map ($mx, $my, 1, 1); |
37 | } |
65 | } |
38 | |
66 | |
39 | sub INIT_INSTANCE { |
67 | sub INIT_INSTANCE { |
40 | my ($self) = @_; |
68 | my ($self) = @_; |
41 | |
69 | |
42 | $self->signal_connect (button_release_event => sub { |
|
|
43 | my ($self, $event) = @_; |
|
|
44 | return unless defined $self->{map}; |
|
|
45 | |
|
|
46 | my ($mx, $my) = $self->{map}->coord ($event->x, $event->y); |
|
|
47 | my $s = $self->get_tile_stack ($mx, $my); |
|
|
48 | $self->signal_emit (update_stack_view => $mx, $my, $s); |
|
|
49 | }); |
|
|
50 | $self->signal_connect ('delete-event' => sub { |
70 | $self->signal_connect ('delete-event' => sub { |
51 | Gtk2->main_quit; |
71 | Gtk2->main_quit; |
52 | }); |
72 | }); |
53 | $self->set_title ("gce - main window"); |
73 | $self->set_title ("gce - main window"); |
54 | |
74 | |
… | |
… | |
82 | "_Clear All" => { |
102 | "_Clear All" => { |
83 | callback => sub { die "NO IMPL" }, accelerator => "<ctrl>C" |
103 | callback => sub { die "NO IMPL" }, accelerator => "<ctrl>C" |
84 | }, |
104 | }, |
85 | "_Attributes" => { |
105 | "_Attributes" => { |
86 | callback => sub { |
106 | callback => sub { |
|
|
107 | return if defined $self->{attr_edit}; |
87 | my $w = Gtk2::Window->new; |
108 | my $w = Gtk2::Window->new; |
88 | $w->set_title ("Edit attrs"); |
109 | $w->set_title ("gce - edit attrs"); |
89 | $w->add (GCE::AttrEdit->new); |
110 | $w->add ($self->{attr_edit} = GCE::AttrEdit->new); |
|
|
111 | $w->signal_connect ('delete-event' => sub { delete $self->{attr_edit} }); |
90 | $w->show_all; |
112 | $w->show_all; |
91 | }, |
113 | }, |
92 | accelerator => "<ctrl>A" |
114 | accelerator => "<ctrl>A" |
93 | }, |
115 | }, |
94 | "Open _Picker" => { |
116 | "Open _Picker" => { |
95 | callback => sub { |
117 | callback => sub { |
96 | my $p = GCE::PickWindow->new; |
118 | my $p = GCE::PickWindow->new ( |
|
|
119 | set_sel_cb => sub { $self->update_pick ($_[0]) }, |
|
|
120 | arch_edit_cb => sub { $self->{attr_edit} and $self->{attr_edit}->set_arch ($_[0]) } |
|
|
121 | ); |
97 | $p->init ($self); |
122 | $p->init; |
98 | }, accelerator => "<ctrl>P" |
123 | }, accelerator => "<ctrl>P" |
99 | }, |
124 | }, |
100 | ] |
125 | ] |
101 | } |
126 | } |
102 | ]; |
127 | ]; |
… | |
… | |
104 | menu_tree => $menu_tree, |
129 | menu_tree => $menu_tree, |
105 | default_callback => \&default_cb, |
130 | default_callback => \&default_cb, |
106 | ); |
131 | ); |
107 | |
132 | |
108 | $self->add (my $vb = Gtk2::VBox->new); |
133 | $self->add (my $vb = Gtk2::VBox->new); |
109 | $vb->pack_start ($men->{widget}, 0, 1, 0); |
134 | $vb->pack_start ($men->{widget}, 0, 1, 0); |
|
|
135 | $vb->pack_start (my $lbl = Gtk2::Label->new ("no selection"), 0, 1, 0); |
|
|
136 | $self->{pick_view} = $lbl; |
|
|
137 | |
110 | $self->add_accel_group ($men->{accel_group}); |
138 | $self->add_accel_group ($men->{accel_group}); |
111 | |
139 | |
112 | my $map = new Crossfire::MapWidget; |
140 | my $map = new Crossfire::MapWidget; |
113 | # XXX:load $ARGV _cleanly_? |
141 | # XXX:load $ARGV _cleanly_? |
114 | my $path = $ARGV[0] || "$Crossfire::LIB/maps/dragonisland/advguild3"; |
142 | my $path = $ARGV[0] || "$Crossfire::LIB/maps/dragonisland/advguild3"; |
115 | $map->set_map (arch2map read_arch $path); |
143 | $map->set_map (arch2map read_arch $path); |
116 | $self->{map} = $map; |
144 | $self->{map} = $map; |
117 | |
145 | |
|
|
146 | |
|
|
147 | $map->signal_connect (button_press_event => sub { |
|
|
148 | my ($mself, $event) = @_; |
|
|
149 | return 0 unless defined $self->{map}; |
|
|
150 | |
|
|
151 | if ($event->button == 1) { |
|
|
152 | $self->{draw_mode} = 1; |
|
|
153 | return 1; |
|
|
154 | |
|
|
155 | } elsif ($event->button == 3) { |
|
|
156 | $self->{draw_mode} = 2; |
|
|
157 | return 1; |
|
|
158 | } |
|
|
159 | |
|
|
160 | 0 |
|
|
161 | }); |
|
|
162 | |
|
|
163 | $map->signal_connect (motion_notify_event => sub { |
|
|
164 | my ($mself, $event) = @_; |
|
|
165 | |
|
|
166 | if ($self->{draw_mode} == 1) { |
|
|
167 | $self->place_pick ($event->x, $event->y); |
|
|
168 | |
|
|
169 | return 1; |
|
|
170 | } elsif ($self->{draw_mode} == 2) { |
|
|
171 | $self->delete_arch ($event->x, $event->y); |
|
|
172 | |
|
|
173 | return 1; |
|
|
174 | } |
|
|
175 | }); |
|
|
176 | $self->signal_connect (button_release_event => sub { |
|
|
177 | my ($mself, $event) = @_; |
|
|
178 | |
|
|
179 | delete $self->{draw_mode}; |
|
|
180 | if ($event->button == 1 && $event->state * "shift-mask") { |
|
|
181 | return 0 unless defined $self->{attr_edit}; |
|
|
182 | $self->{attr_edit}->set_arch ($self->get_top_arch ($event->x, $event->y)); |
|
|
183 | return 1; |
|
|
184 | } elsif ($event->button == 1) { |
|
|
185 | $self->place_pick ($event->x, $event->y); |
|
|
186 | return 1; |
|
|
187 | |
|
|
188 | } elsif ($event->button == 3) { |
|
|
189 | $self->delete_arch ($event->x, $event->y); |
|
|
190 | return 1; |
|
|
191 | } |
|
|
192 | }); |
|
|
193 | |
|
|
194 | |
|
|
195 | |
118 | $vb->pack_start ($map, 1, 1, 0); |
196 | $vb->pack_start ($map, 1, 1, 0); |
119 | } |
197 | } |
120 | |
198 | |
121 | sub new_cb { |
199 | sub new_cb { |
122 | my ($self) = @_; |
200 | my ($self) = @_; |
… | |
… | |
128 | |
206 | |
129 | my $fc = Gtk2::FileChooserDialog->new ( |
207 | my $fc = Gtk2::FileChooserDialog->new ( |
130 | 'Open map', undef, 'open', 'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok' |
208 | 'Open map', undef, 'open', 'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok' |
131 | ); |
209 | ); |
132 | $fc->add_shortcut_folder ("$Crossfire::LIB/maps"); |
210 | $fc->add_shortcut_folder ("$Crossfire::LIB/maps"); |
|
|
211 | $fc->set_current_folder ($self->{fc_last_folder} || "$Crossfire::LIB/maps"); |
133 | |
212 | |
134 | if ('ok' eq $fc->run) { |
213 | if ('ok' eq $fc->run) { |
135 | my $map = arch2map read_arch $fc->get_filename; |
214 | my $map = arch2map read_arch $fc->get_filename; |
|
|
215 | $self->{fc_last_folder} = $fc->get_current_folder; |
136 | $self->{map}->set_map ($map); |
216 | $self->{map}->set_map ($map); |
137 | $self->{map}->hide; |
217 | $self->{map}->hide; |
138 | $self->{map}->show_all; |
218 | $self->{map}->show_all; |
139 | } |
219 | } |
140 | |
220 | |
141 | $fc->destroy; |
221 | $fc->destroy; |
142 | } |
222 | } |
143 | |
223 | |
|
|
224 | sub update_pick { |
|
|
225 | my ($self, $arch) = @_; |
|
|
226 | |
|
|
227 | $self->{pick_arch} = $arch; |
|
|
228 | $self->{pick_view}->set_text ($arch->{_name}); |
|
|
229 | } |
|
|
230 | |
144 | =head1 AUTHOR |
231 | =head1 AUTHOR |
145 | |
232 | |
146 | Marc Lehmann <schmorp@schmorp.de> |
233 | Marc Lehmann <schmorp@schmorp.de> |
147 | http://home.schmorp.de/ |
234 | http://home.schmorp.de/ |
148 | |
235 | |