NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / win / Qt / tileedit.cpp
blob5103a85b428c57e8faa661ee729e5b680ff3d282
1 /* aNetHack 0.0.1 tileedit.cpp $ANH-Date$ $ANH-Branch$:$ANH-Revision$ */
2 /* Copyright (c) Warwick Allison, 1999. */
3 /* aNetHack may be freely redistributed. See license for details. */
4 /*
5 Build this little utility program if you want to use it to edit the tile
6 files. Move tileedit.cpp and tileedit.h to ../../util, add the
7 3 lines below to the Makefile there and "make tileedit".
9 tileedit: tileedit.cpp $(TEXT_IO)
10 moc -o tileedit.moc tileedit.h
11 $(CC) -o tileedit -I../include -I$(QTDIR)/include -L$(QTDIR)/lib tileedit.cpp $(TEXT_IO) -lqt
15 #include "tileedit.h"
16 #include <qapplication.h>
17 #include <qmainwindow.h>
18 #include <qkeycode.h>
19 #include <qpopupmenu.h>
20 #include <qmenubar.h>
21 #include <qpainter.h>
22 #include <qstatusbar.h>
23 #include <qhbox.h>
24 #include <qlabel.h>
26 extern "C" {
27 #include "config.h"
28 #include "tile.h"
29 extern const char *FDECL(tilename, (int, int));
32 #define TILES_ACROSS 20
34 TilePickerTab::TilePickerTab(const char* basename, int i, QWidget* parent) :
35 QWidget(parent)
37 id = i;
38 filename = basename;
39 filename += ".txt";
40 num = 0;
41 int index = 0;
42 for (int real=0; real<2; real++) {
43 if ( real ) {
44 image.create( TILES_ACROSS*TILE_X,
45 ((num+TILES_ACROSS-1)/TILES_ACROSS)*TILE_Y, 32 );
47 if ( !fopen_text_file(filename.latin1(), RDTMODE) ) {
48 // XXX handle better
49 exit(1);
51 pixel p[TILE_Y][TILE_X];
52 while ( read_text_tile(p) ) {
53 if ( real ) {
54 int ox = (index%TILES_ACROSS)*TILE_X;
55 int oy = (index/TILES_ACROSS)*TILE_Y;
56 for ( int y=0; y<TILE_Y; y++ ) {
57 QRgb* rgb = ((QRgb*)image.scanLine(oy+y)) + ox;
58 for ( int x=0; x<TILE_X; x++ ) {
59 *rgb++ = qRgb(p[y][x].r, p[y][x].g, p[y][x].b);
62 index++;
63 } else {
64 // Just count...
65 num++;
68 fclose_text_file();
70 image = image.convertDepth( 8, AvoidDither );
71 pixmap.convertFromImage( image );
74 bool TilePickerTab::save()
76 if ( !fopen_text_file(filename.latin1(), WRTMODE) ) {
77 // XXX handle better
78 exit(1);
80 pixel p[TILE_Y][TILE_X];
81 for ( int index=0; index < num; index++ ) {
82 int ox = (index%TILES_ACROSS)*TILE_X;
83 int oy = (index/TILES_ACROSS)*TILE_Y;
84 for ( int y=0; y<TILE_Y; y++ ) {
85 uchar* c = image.scanLine(oy+y) + ox;
86 for ( int x=0; x<TILE_X; x++ ) {
87 QRgb rgb = image.color(*c++);
88 p[y][x].r = qRed(rgb);
89 p[y][x].g = qGreen(rgb);
90 p[y][x].b = qBlue(rgb);
93 write_text_tile(p);
95 fclose_text_file();
98 void TilePickerTab::mousePressEvent(QMouseEvent* e)
100 int ox = e->x()-e->x()%TILE_X;
101 int oy = e->y()-e->y()%TILE_Y;
102 QImage subimage = image.copy(ox,oy,TILE_X,TILE_Y);
103 if ( e->button() == RightButton ) {
104 setCurrent(subimage);
105 } else {
106 last_pick = ox/TILE_X + oy/TILE_Y*TILES_ACROSS;
108 emit pick(subimage);
109 emit pickName(tilename(id, last_pick));
112 void TilePickerTab::setCurrent(const QImage& i)
114 int ox = last_pick%TILES_ACROSS * TILE_X;
115 int oy = last_pick/TILES_ACROSS * TILE_Y;
116 bitBlt( &image, ox, oy, &i );
117 bitBlt( &pixmap, ox, oy, &i );
118 repaint( ox, oy, TILE_X, TILE_Y, FALSE );
121 QSize TilePickerTab::sizeHint() const
123 return pixmap.size();
126 void TilePickerTab::paintEvent( QPaintEvent* )
128 QPainter p(this);
129 p.drawPixmap(0,0,pixmap);
132 static struct {
133 const char* name;
134 TilePickerTab* tab;
135 } tileset[] = {
136 { "monsters", 0 },
137 { "objects", 0 },
138 { "other", 0 },
139 { 0 }
142 TilePicker::TilePicker(QWidget* parent) :
143 QTabWidget(parent)
145 for (int i=0; tileset[i].name; i++) {
146 QString tabname = tileset[i].name;
147 tabname[0] = tabname[0].upper();
148 tileset[i].tab = new TilePickerTab(tileset[i].name,i+1,this);
149 addTab( tileset[i].tab, tabname );
150 connect( tileset[i].tab, SIGNAL(pick(const QImage&)),
151 this, SIGNAL(pick(const QImage&)) );
152 connect( tileset[i].tab, SIGNAL(pickName(const QString&)),
153 this, SIGNAL(pickName(const QString&)) );
157 void TilePicker::setCurrent(const QImage& i)
159 ((TilePickerTab*)currentPage())->setCurrent(i);
162 void TilePicker::save()
164 for (int i=0; tileset[i].tab; i++) {
165 tileset[i].tab->save();
169 TrivialTileEditor::TrivialTileEditor( QWidget* parent ) :
170 QWidget(parent)
174 const QImage& TrivialTileEditor::image() const
176 return img;
179 void TrivialTileEditor::setColor( QRgb rgb )
181 pen = rgb;
182 for (penpixel = 0;
183 penpixel<img.numColors()-1 && (img.color(penpixel)&0xffffff)!=(pen.rgb()&0xffffff);
184 penpixel++)
185 continue;
188 void TrivialTileEditor::setImage( const QImage& i )
190 img = i;
191 setColor(pen.rgb()); // update penpixel
192 repaint(FALSE);
195 void TrivialTileEditor::paintEvent( QPaintEvent* e )
197 QRect r = e->rect();
198 QPoint tl = imagePoint(r.topLeft());
199 QPoint br = imagePoint(r.bottomRight());
200 r = QRect(tl,br).intersect(img.rect());
201 QPainter painter(this);
202 for (int y=r.top(); y<=r.bottom(); y++) {
203 for (int x=r.left(); x<=r.right(); x++) {
204 paintPoint(painter,QPoint(x,y));
209 void TrivialTileEditor::paintPoint(QPainter& painter, QPoint p)
211 QPoint p1 = screenPoint(p);
212 QPoint p2 = screenPoint(p+QPoint(1,1));
213 QColor c = img.color(img.scanLine(p.y())[p.x()]);
214 painter.fillRect(QRect(p1,p2-QPoint(1,1)), c);
217 void TrivialTileEditor::mousePressEvent(QMouseEvent* e)
219 QPoint p = imagePoint(e->pos());
220 if ( !img.rect().contains(p) )
221 return;
222 uchar& pixel = img.scanLine(p.y())[p.x()];
223 if ( e->button() == LeftButton ) {
224 pixel = penpixel;
225 QPainter painter(this);
226 paintPoint(painter,p);
227 } else if ( e->button() == RightButton ) {
228 emit pick( img.color(pixel) );
229 } else if ( e->button() == MidButton ) {
230 QPainter painter(this);
231 if ( pixel != penpixel )
232 fill(painter,p,pixel);
236 void TrivialTileEditor::fill(QPainter& painter, QPoint p, uchar from)
238 if ( img.rect().contains(p) ) {
239 uchar& pixel = img.scanLine(p.y())[p.x()];
240 if ( pixel == from ) {
241 pixel = penpixel;
242 paintPoint(painter,p);
243 fill(painter, p+QPoint(-1,0), from);
244 fill(painter, p+QPoint(+1,0), from);
245 fill(painter, p+QPoint(0,-1), from);
246 fill(painter, p+QPoint(0,+1), from);
251 void TrivialTileEditor::mouseReleaseEvent(QMouseEvent* e)
253 emit edited(image());
256 void TrivialTileEditor::mouseMoveEvent(QMouseEvent* e)
258 QPoint p = imagePoint(e->pos());
259 if ( !img.rect().contains(p) )
260 return;
261 uchar& pixel = img.scanLine(p.y())[p.x()];
262 pixel = penpixel;
263 QPainter painter(this);
264 paintPoint(painter,p);
267 QPoint TrivialTileEditor::imagePoint(QPoint p) const
269 return QPoint(p.x()*TILE_X/width(), p.y()*TILE_Y/height());
272 QPoint TrivialTileEditor::screenPoint(QPoint p) const
274 return QPoint(p.x()*width()/TILE_X, p.y()*height()/TILE_Y);
277 QSizePolicy TrivialTileEditor::sizePolicy() const
279 return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding, TRUE );
282 QSize TrivialTileEditor::sizeHint() const
284 return sizeForWidth(-1);
287 QSize TrivialTileEditor::sizeForWidth(int w) const
289 if ( w < 0 )
290 return QSize(TILE_X*32,TILE_Y*32);
291 else
292 return QSize(w,w*TILE_Y/TILE_X);
296 TilePalette::TilePalette( QWidget* parent ) :
297 QWidget(parent)
299 num = 0;
300 rgb = 0;
303 TilePalette::~TilePalette()
305 delete rgb;
308 void TilePalette::setFromImage( const QImage& i )
310 num = i.numColors();
311 rgb = new QRgb[num];
312 memcpy(rgb, i.colorTable(), num*sizeof(QRgb));
313 repaint(FALSE);
316 void TilePalette::setColor(QRgb c)
318 for (int i=0; i<num; i++)
319 if ( c == rgb[i] ) {
320 emit pick(c);
321 return;
325 QSizePolicy TilePalette::sizePolicy() const
327 return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum, FALSE );
330 QSize TilePalette::sizeHint() const
332 return QSize(num*16,16);
335 void TilePalette::paintEvent( QPaintEvent* )
337 QPainter p(this);
338 for (int i=0; i<num; i++) {
339 int x1 = width()*i/num;
340 int x2 = width()*(i+1)/num;
341 p.fillRect(x1,0,x2-x1,height(),QColor(rgb[i]));
345 void TilePalette::mousePressEvent(QMouseEvent* e)
347 int c = e->x()*num/width();
348 emit pick(rgb[c]);
351 TileEditor::TileEditor(QWidget* parent) :
352 QVBox(parent),
353 editor(this),
354 palette(this)
356 connect( &palette, SIGNAL(pick(QRgb)),
357 &editor, SLOT(setColor(QRgb)) );
358 connect( &editor, SIGNAL(pick(QRgb)),
359 &palette, SLOT(setColor(QRgb)) );
360 connect( &editor, SIGNAL(edited(const QImage&)),
361 this, SIGNAL(edited(const QImage&)) );
364 void TileEditor::edit(const QImage& i)
366 editor.setImage(i);
367 palette.setFromImage(i);
370 const QImage& TileEditor::image() const
372 return editor.image();
375 class Main : public QMainWindow {
376 public:
377 Main() :
378 central(this),
379 editor(&central),
380 picker(&central)
382 QPopupMenu* file = new QPopupMenu(menuBar());
383 file->insertItem("&Save", &picker, SLOT(save()), CTRL+Key_S);
384 file->insertSeparator();
385 file->insertItem("&Exit", qApp, SLOT(quit()), CTRL+Key_Q);
386 menuBar()->insertItem("&File", file);
388 connect( &picker, SIGNAL(pick(const QImage&)),
389 &editor, SLOT(edit(const QImage&)) );
390 connect( &picker, SIGNAL(pickName(const QString&)),
391 statusBar(), SLOT(message(const QString&)) );
392 connect( &editor, SIGNAL(edited(const QImage&)),
393 &picker, SLOT(setCurrent(const QImage&)) );
395 setCentralWidget(&central);
398 private:
399 QHBox central;
400 TileEditor editor;
401 TilePicker picker;
404 main(int argc, char** argv)
406 QApplication app(argc,argv);
407 Main m;
408 app.setMainWidget(&m);
409 m.show();
410 return app.exec();
413 #include "tileedit.moc"