1 // Copyright (C) 2009, 2010, 2011, 2014, 2020 Ben Asselstine
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 // 02110-1301, USA.
17
18 #include <config.h>
19
20 #include <gtkmm.h>
21 #include <sigc++/functors/mem_fun.h>
22
23 #include "tileset-explosion-picture-editor-dialog.h"
24
25 #include "ucompose.hpp"
26 #include "defs.h"
27 #include "File.h"
28 #include "ImageCache.h"
29 #include "tarhelper.h"
30 #include "tile-preview-scene.h"
31 #include "tileset-window.h"
32 #include "past-chooser.h"
33 #include "font-size.h"
34 #include "image-file-filter.h"
35 #include "timed-message-dialog.h"
36
37 #define method(x) sigc::mem_fun(*this, &TilesetExplosionPictureEditorDialog::x)
38
TilesetExplosionPictureEditorDialog(Gtk::Window & parent,Tileset * tileset)39 TilesetExplosionPictureEditorDialog::TilesetExplosionPictureEditorDialog(Gtk::Window &parent, Tileset *tileset)
40 : LwEditorDialog(parent, "tileset-explosion-picture-editor-dialog.ui")
41 {
42 d_changed = false;
43 d_tileset = tileset;
44
45 xml->get_widget("explosion_imagebutton", explosion_imagebutton);
46 explosion_imagebutton->signal_clicked().connect
47 (method(on_explosion_imagebutton_clicked));
48
49 xml->get_widget("large_explosion_radiobutton", large_explosion_radiobutton);
50 large_explosion_radiobutton->signal_toggled().connect (method(on_large_toggled));
51 xml->get_widget("small_explosion_radiobutton", small_explosion_radiobutton);
52 small_explosion_radiobutton->signal_toggled().connect (method(on_small_toggled));
53
54 xml->get_widget("scene_image", scene_image);
55
56 Glib::ustring imgname = d_tileset->getExplosionFilename();
57 if (imgname.empty() == false)
58 {
59 bool broken = false;
60 Glib::ustring f =
61 d_tileset->getFileFromConfigurationFile(imgname);
62 d_explosion = PixMask::create (f, broken);
63 }
64 else
65 d_explosion = NULL;
66 on_large_toggled();
67 }
68
run()69 bool TilesetExplosionPictureEditorDialog::run()
70 {
71 dialog->show_all();
72 dialog->run();
73 dialog->hide ();
74 return d_changed;
75 }
76
on_image_chosen(Gtk::FileChooserDialog * d)77 bool TilesetExplosionPictureEditorDialog::on_image_chosen(Gtk::FileChooserDialog *d)
78 {
79 bool broken = false;
80 d_explosion = PixMask::create (d->get_filename (), broken);
81 if (!broken)
82 {
83 Glib::ustring imgname = d_tileset->getExplosionFilename();
84 Glib::ustring newname = "";
85 bool success = false;
86 if (imgname.empty() == true)
87 success =
88 d_tileset->addFileInCfgFile(d->get_filename(), newname);
89 else
90 success =
91 d_tileset->replaceFileInCfgFile(imgname, d->get_filename(), newname);
92 if (success)
93 {
94 d_tileset->setExplosionFilename (newname);
95 d_tileset->instantiateExplosionImage();
96 d_changed = true;
97 update_panel ();
98 }
99 else
100 {
101 Glib::ustring errmsg = Glib::strerror(errno);
102 TimedMessageDialog
103 td(*d, String::ucompose(_("Couldn't add %1 to :\n%2\n%3"),
104 d->get_filename (),
105 d_tileset->getConfigurationFile(),
106 errmsg), 0);
107 td.run_and_hide ();
108 broken = true;
109 }
110 }
111 else
112 {
113 TimedMessageDialog
114 td(*d, String::ucompose(_("Couldn't make sense of the image:\n%1"),
115 d->get_filename ()), 0);
116 td.run_and_hide ();
117 broken = true;
118 }
119 return broken;
120 }
121
on_large_toggled()122 void TilesetExplosionPictureEditorDialog::on_large_toggled()
123 {
124 update_panel();
125 }
126
on_small_toggled()127 void TilesetExplosionPictureEditorDialog::on_small_toggled()
128 {
129 update_panel();
130 }
131
update_panel()132 void TilesetExplosionPictureEditorDialog::update_panel()
133 {
134 Glib::ustring imgname = d_tileset->getExplosionFilename();
135 if (imgname.empty() == false)
136 {
137 explosion_imagebutton->set_label (imgname);
138 show_explosion_image();
139 }
140 else
141 {
142 explosion_imagebutton->set_label (_("no image set"));
143 scene_image->clear();
144 }
145 }
146
show_explosion_image()147 void TilesetExplosionPictureEditorDialog::show_explosion_image()
148 {
149 guint32 size = FontSize::getInstance ()->get_height () *
150 EDITOR_DIALOG_TILE_PIC_FONTSIZE_MULTIPLE;
151 TilePreviewScene *s;
152 Glib::ustring scene;
153 guint32 idx = d_tileset->getIndex(Tile::GRASS);
154 Tile *grass = NULL;
155 if (d_tileset->size() > 0)
156 grass = (*d_tileset)[idx];
157 scene.clear();
158 if (large_explosion_radiobutton->get_active() == true)
159 {
160 scene += "aaaaaa";
161 scene += "aaaaaa";
162 scene += "aaaaaa";
163 scene += "aaaaaa";
164 scene += "aaaaaa";
165 scene += "aaaaaa";
166 s = new TilePreviewScene(grass, NULL, 6, 6, scene, size);
167 update_scene(s);
168 }
169 else if (small_explosion_radiobutton->get_active() == true)
170 {
171 scene += "aaaaaaa";
172 scene += "aaaaaaa";
173 scene += "aaaaaaa";
174 scene += "aaaaaaa";
175 scene += "aaaaaaa";
176 scene += "aaaaaaa";
177 scene += "aaaaaaa";
178 s = new TilePreviewScene(grass, NULL, 7, 7, scene, size);
179 update_scene(s);
180 }
181 }
182
update_scene(TilePreviewScene * scene)183 void TilesetExplosionPictureEditorDialog::update_scene(TilePreviewScene *scene)
184 {
185 if (!d_explosion)
186 return;
187 if (!scene)
188 return;
189
190 Glib::RefPtr<Gdk::Pixbuf> scene_pixbuf;
191 scene_pixbuf = scene->renderScene ();
192 //center the explosion image on the pixbuf
193 //but the large explosion is scaled first
194
195 Glib::RefPtr<Gdk::Pixbuf> explosion;
196 if (small_explosion_radiobutton->get_active())
197 {
198 //explosion = d_explosion->to_pixbuf ();
199 PixMask *p = d_explosion->copy ();
200 double ratio = EDITOR_DIALOG_TILE_PIC_FONTSIZE_MULTIPLE;
201 double new_height = FontSize::getInstance()->get_height () * ratio;
202 int new_width =
203 ImageCache::calculate_width_from_adjusted_height (p, new_height);
204 PixMask::scale (p, new_width, new_height);
205 explosion = p->to_pixbuf ();
206 delete p;
207 }
208 else if (large_explosion_radiobutton->get_active())
209 {
210 PixMask *p = d_explosion->copy ();
211 double ratio = EDITOR_DIALOG_TILE_PIC_FONTSIZE_MULTIPLE;
212 double new_height = FontSize::getInstance()->get_height () * ratio * 2.0;
213 int new_width =
214 ImageCache::calculate_width_from_adjusted_height (p, new_height);
215 PixMask::scale (p, new_width, new_height);
216 explosion = p->to_pixbuf ();
217 //guint32 ts = d_tileset->getTileSize ();
218 //PixMask::scale (p, ts * 2, ts * 2);
219 //explosion = p->to_pixbuf ();
220 delete p;
221 }
222
223 int i = (scene_pixbuf->get_width() - explosion->get_width()) / 2;
224 int j = (scene_pixbuf->get_height() - explosion->get_height()) / 2;
225 explosion->composite (scene_pixbuf, i, j, explosion->get_width(), explosion->get_height(), i, j, 1, 1, Gdk::INTERP_NEAREST, 255);
226 scene_image->property_pixbuf() = scene_pixbuf;
227 scene_image->queue_draw();
228 }
229
image_filechooser(bool clear)230 Gtk::FileChooserDialog* TilesetExplosionPictureEditorDialog::image_filechooser(bool clear)
231 {
232 Glib::ustring filename = "";
233 Glib::ustring title = _("Choose an explosion image");
234 Gtk::FileChooserDialog *d = new Gtk::FileChooserDialog(*dialog, title);
235 ImageFileFilter::getInstance ()->add (d);
236 d->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
237 d->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
238 if (clear)
239 d->add_button(Gtk::Stock::CLEAR, Gtk::RESPONSE_REJECT);
240 d->set_default_response(Gtk::RESPONSE_ACCEPT);
241 d->set_current_folder(PastChooser::getInstance()->get_dir(d));
242 return d;
243 }
244
on_explosion_imagebutton_clicked()245 void TilesetExplosionPictureEditorDialog::on_explosion_imagebutton_clicked ()
246 {
247 Glib::ustring f = d_tileset->getExplosionFilename ();
248 Glib::ustring filename = "";
249 Gtk::FileChooserDialog *d = image_filechooser(f != "");
250 if (f != "")
251 filename = d_tileset->getFileFromConfigurationFile(f);
252 int response = d->run();
253 if (filename != "")
254 File::erase(filename);
255 if (response == Gtk::RESPONSE_ACCEPT && d->get_filename() != "")
256 {
257 if (ImageFileFilter::getInstance ()->hasInvalidExt (d->get_filename ()))
258 ImageFileFilter::getInstance()->showErrorDialog (d);
259 else
260 {
261 if (d->get_filename() != filename)
262 {
263 PastChooser::getInstance()->set_dir(d);
264 on_image_chosen (d);
265 }
266 }
267 }
268 else if (response == Gtk::RESPONSE_REJECT && f != "")
269 {
270 if (d_tileset->removeFileInCfgFile(f))
271 {
272 d_changed = true;
273 d_tileset->uninstantiateSameNamedImages (f);
274 if (d_explosion)
275 {
276 delete d_explosion;
277 d_explosion = NULL;
278 }
279 update_panel ();
280 }
281 else
282 {
283 Glib::ustring errmsg = Glib::strerror(errno);
284 TimedMessageDialog
285 td(*d, String::ucompose(_("Couldn't remove %1 from:\n%2\n%3"),
286 f, d_tileset->getConfigurationFile(),
287 errmsg), 0);
288 td.run_and_hide ();
289 }
290 }
291 d->hide();
292 delete d;
293 }
294
~TilesetExplosionPictureEditorDialog()295 TilesetExplosionPictureEditorDialog::~TilesetExplosionPictureEditorDialog ()
296 {
297 if (d_explosion)
298 delete d_explosion;
299 }
300