*** empty log message ***
This commit is contained in:
408
win/Qt/tileedit.cpp
Normal file
408
win/Qt/tileedit.cpp
Normal file
@@ -0,0 +1,408 @@
|
||||
/* SCCS Id: @(#)tileedit.cpp 3.3 1999/11/19 */
|
||||
/* Copyright (c) Warwick Allison, 1999. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
/*
|
||||
Build this little utility program if you want to use it to edit the tile
|
||||
files. Move tileedit.cpp and tileedit.h to ../../util, add the
|
||||
3 lines below to the Makefile there and "make tileedit".
|
||||
|
||||
tileedit: tileedit.cpp $(TEXT_IO)
|
||||
moc -o tileedit.moc tileedit.h
|
||||
$(CC) -o tileedit -I../include -I$(QTDIR)/include -L$(QTDIR)/lib tileedit.cpp $(TEXT_IO) -lqt
|
||||
*/
|
||||
|
||||
|
||||
#include "tileedit.h"
|
||||
#include <qapplication.h>
|
||||
#include <qmainwindow.h>
|
||||
#include <qkeycode.h>
|
||||
#include <qpopupmenu.h>
|
||||
#include <qmenubar.h>
|
||||
#include <qpainter.h>
|
||||
#include <qstatusbar.h>
|
||||
#include <qhbox.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
extern "C" {
|
||||
#include "config.h"
|
||||
#include "tile.h"
|
||||
extern const char *FDECL(tilename, (int, int));
|
||||
}
|
||||
|
||||
#define TILES_ACROSS 20
|
||||
|
||||
TilePickerTab::TilePickerTab(const char* basename, int i, QWidget* parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
id = i;
|
||||
filename = basename;
|
||||
filename += ".txt";
|
||||
num = 0;
|
||||
int index = 0;
|
||||
for (int real=0; real<2; real++) {
|
||||
if ( real ) {
|
||||
image.create( TILES_ACROSS*TILE_X,
|
||||
((num+TILES_ACROSS-1)/TILES_ACROSS)*TILE_Y, 32 );
|
||||
}
|
||||
if ( !fopen_text_file(filename.latin1(), RDTMODE) ) {
|
||||
// XXX handle better
|
||||
exit(1);
|
||||
}
|
||||
pixel p[TILE_Y][TILE_X];
|
||||
while ( read_text_tile(p) ) {
|
||||
if ( real ) {
|
||||
int ox = (index%TILES_ACROSS)*TILE_X;
|
||||
int oy = (index/TILES_ACROSS)*TILE_Y;
|
||||
for ( int y=0; y<TILE_Y; y++ ) {
|
||||
QRgb* rgb = ((QRgb*)image.scanLine(oy+y)) + ox;
|
||||
for ( int x=0; x<TILE_X; x++ ) {
|
||||
*rgb++ = qRgb(p[y][x].r, p[y][x].g, p[y][x].b);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
} else {
|
||||
// Just count...
|
||||
num++;
|
||||
}
|
||||
}
|
||||
fclose_text_file();
|
||||
}
|
||||
image = image.convertDepth( 8, AvoidDither );
|
||||
pixmap.convertFromImage( image );
|
||||
}
|
||||
|
||||
bool TilePickerTab::save()
|
||||
{
|
||||
if ( !fopen_text_file(filename.latin1(), WRTMODE) ) {
|
||||
// XXX handle better
|
||||
exit(1);
|
||||
}
|
||||
pixel p[TILE_Y][TILE_X];
|
||||
for ( int index=0; index < num; index++ ) {
|
||||
int ox = (index%TILES_ACROSS)*TILE_X;
|
||||
int oy = (index/TILES_ACROSS)*TILE_Y;
|
||||
for ( int y=0; y<TILE_Y; y++ ) {
|
||||
uchar* c = image.scanLine(oy+y) + ox;
|
||||
for ( int x=0; x<TILE_X; x++ ) {
|
||||
QRgb rgb = image.color(*c++);
|
||||
p[y][x].r = qRed(rgb);
|
||||
p[y][x].g = qGreen(rgb);
|
||||
p[y][x].b = qBlue(rgb);
|
||||
}
|
||||
}
|
||||
write_text_tile(p);
|
||||
}
|
||||
fclose_text_file();
|
||||
}
|
||||
|
||||
void TilePickerTab::mousePressEvent(QMouseEvent* e)
|
||||
{
|
||||
int ox = e->x()-e->x()%TILE_X;
|
||||
int oy = e->y()-e->y()%TILE_Y;
|
||||
QImage subimage = image.copy(ox,oy,TILE_X,TILE_Y);
|
||||
if ( e->button() == RightButton ) {
|
||||
setCurrent(subimage);
|
||||
} else {
|
||||
last_pick = ox/TILE_X + oy/TILE_Y*TILES_ACROSS;
|
||||
}
|
||||
emit pick(subimage);
|
||||
emit pickName(tilename(id, last_pick));
|
||||
}
|
||||
|
||||
void TilePickerTab::setCurrent(const QImage& i)
|
||||
{
|
||||
int ox = last_pick%TILES_ACROSS * TILE_X;
|
||||
int oy = last_pick/TILES_ACROSS * TILE_Y;
|
||||
bitBlt( &image, ox, oy, &i );
|
||||
bitBlt( &pixmap, ox, oy, &i );
|
||||
repaint( ox, oy, TILE_X, TILE_Y, FALSE );
|
||||
}
|
||||
|
||||
QSize TilePickerTab::sizeHint() const
|
||||
{
|
||||
return pixmap.size();
|
||||
}
|
||||
|
||||
void TilePickerTab::paintEvent( QPaintEvent* )
|
||||
{
|
||||
QPainter p(this);
|
||||
p.drawPixmap(0,0,pixmap);
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char* name;
|
||||
TilePickerTab* tab;
|
||||
} tileset[] = {
|
||||
{ "monsters", 0 },
|
||||
{ "objects", 0 },
|
||||
{ "other", 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
TilePicker::TilePicker(QWidget* parent) :
|
||||
QTabWidget(parent)
|
||||
{
|
||||
for (int i=0; tileset[i].name; i++) {
|
||||
QString tabname = tileset[i].name;
|
||||
tabname[0] = tabname[0].upper();
|
||||
tileset[i].tab = new TilePickerTab(tileset[i].name,i+1,this);
|
||||
addTab( tileset[i].tab, tabname );
|
||||
connect( tileset[i].tab, SIGNAL(pick(const QImage&)),
|
||||
this, SIGNAL(pick(const QImage&)) );
|
||||
connect( tileset[i].tab, SIGNAL(pickName(const QString&)),
|
||||
this, SIGNAL(pickName(const QString&)) );
|
||||
}
|
||||
}
|
||||
|
||||
void TilePicker::setCurrent(const QImage& i)
|
||||
{
|
||||
((TilePickerTab*)currentPage())->setCurrent(i);
|
||||
}
|
||||
|
||||
void TilePicker::save()
|
||||
{
|
||||
for (int i=0; tileset[i].tab; i++) {
|
||||
tileset[i].tab->save();
|
||||
}
|
||||
}
|
||||
|
||||
TrivialTileEditor::TrivialTileEditor( QWidget* parent ) :
|
||||
QWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
const QImage& TrivialTileEditor::image() const
|
||||
{
|
||||
return img;
|
||||
}
|
||||
|
||||
void TrivialTileEditor::setColor( QRgb rgb )
|
||||
{
|
||||
pen = rgb;
|
||||
for (penpixel = 0;
|
||||
penpixel<img.numColors()-1 && img.color(penpixel)!=pen.rgb();
|
||||
penpixel++)
|
||||
continue;
|
||||
}
|
||||
|
||||
void TrivialTileEditor::setImage( const QImage& i )
|
||||
{
|
||||
img = i;
|
||||
setColor(pen.rgb()); // update penpixel
|
||||
repaint(FALSE);
|
||||
}
|
||||
|
||||
void TrivialTileEditor::paintEvent( QPaintEvent* e )
|
||||
{
|
||||
QRect r = e->rect();
|
||||
QPoint tl = imagePoint(r.topLeft());
|
||||
QPoint br = imagePoint(r.bottomRight());
|
||||
r = QRect(tl,br).intersect(img.rect());
|
||||
QPainter painter(this);
|
||||
for (int y=r.top(); y<=r.bottom(); y++) {
|
||||
for (int x=r.left(); x<=r.right(); x++) {
|
||||
paintPoint(painter,QPoint(x,y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrivialTileEditor::paintPoint(QPainter& painter, QPoint p)
|
||||
{
|
||||
QPoint p1 = screenPoint(p);
|
||||
QPoint p2 = screenPoint(p+QPoint(1,1));
|
||||
QColor c = img.color(img.scanLine(p.y())[p.x()]);
|
||||
painter.fillRect(QRect(p1,p2-QPoint(1,1)), c);
|
||||
}
|
||||
|
||||
void TrivialTileEditor::mousePressEvent(QMouseEvent* e)
|
||||
{
|
||||
QPoint p = imagePoint(e->pos());
|
||||
uchar& pixel = img.scanLine(p.y())[p.x()];
|
||||
if ( e->button() == LeftButton ) {
|
||||
pixel = penpixel;
|
||||
QPainter painter(this);
|
||||
paintPoint(painter,p);
|
||||
} else if ( e->button() == RightButton ) {
|
||||
emit pick( img.color(pixel) );
|
||||
} else if ( e->button() == MidButton ) {
|
||||
QPainter painter(this);
|
||||
fill(painter,p,pixel);
|
||||
}
|
||||
}
|
||||
|
||||
void TrivialTileEditor::fill(QPainter& painter, QPoint p, uchar from)
|
||||
{
|
||||
if ( img.rect().contains(p) ) {
|
||||
uchar& pixel = img.scanLine(p.y())[p.x()];
|
||||
if ( pixel == from ) {
|
||||
pixel = penpixel;
|
||||
paintPoint(painter,p);
|
||||
fill(painter, p+QPoint(-1,0), from);
|
||||
fill(painter, p+QPoint(+1,0), from);
|
||||
fill(painter, p+QPoint(0,-1), from);
|
||||
fill(painter, p+QPoint(0,+1), from);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrivialTileEditor::mouseReleaseEvent(QMouseEvent* e)
|
||||
{
|
||||
emit edited(image());
|
||||
}
|
||||
|
||||
void TrivialTileEditor::mouseMoveEvent(QMouseEvent* e)
|
||||
{
|
||||
QPoint p = imagePoint(e->pos());
|
||||
uchar& pixel = img.scanLine(p.y())[p.x()];
|
||||
pixel = penpixel;
|
||||
QPainter painter(this);
|
||||
paintPoint(painter,p);
|
||||
}
|
||||
|
||||
QPoint TrivialTileEditor::imagePoint(QPoint p) const
|
||||
{
|
||||
return QPoint(p.x()*TILE_X/width(), p.y()*TILE_Y/height());
|
||||
}
|
||||
|
||||
QPoint TrivialTileEditor::screenPoint(QPoint p) const
|
||||
{
|
||||
return QPoint(p.x()*width()/TILE_X, p.y()*height()/TILE_Y);
|
||||
}
|
||||
|
||||
QSizePolicy TrivialTileEditor::sizePolicy() const
|
||||
{
|
||||
return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding, TRUE );
|
||||
}
|
||||
|
||||
QSize TrivialTileEditor::sizeHint() const
|
||||
{
|
||||
return sizeForWidth(-1);
|
||||
}
|
||||
|
||||
QSize TrivialTileEditor::sizeForWidth(int w) const
|
||||
{
|
||||
if ( w < 0 )
|
||||
return QSize(TILE_X*32,TILE_Y*32);
|
||||
else
|
||||
return QSize(w,w*TILE_Y/TILE_X);
|
||||
}
|
||||
|
||||
|
||||
TilePalette::TilePalette( QWidget* parent ) :
|
||||
QWidget(parent)
|
||||
{
|
||||
num = 0;
|
||||
rgb = 0;
|
||||
}
|
||||
|
||||
TilePalette::~TilePalette()
|
||||
{
|
||||
delete rgb;
|
||||
}
|
||||
|
||||
void TilePalette::setFromImage( const QImage& i )
|
||||
{
|
||||
num = i.numColors();
|
||||
rgb = new QRgb[num];
|
||||
memcpy(rgb, i.colorTable(), num*sizeof(QRgb));
|
||||
repaint(FALSE);
|
||||
}
|
||||
|
||||
void TilePalette::setColor(QRgb c)
|
||||
{
|
||||
for (int i=0; i<num; i++)
|
||||
if ( c == rgb[i] ) {
|
||||
emit pick(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QSizePolicy TilePalette::sizePolicy() const
|
||||
{
|
||||
return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum, FALSE );
|
||||
}
|
||||
|
||||
QSize TilePalette::sizeHint() const
|
||||
{
|
||||
return QSize(num*16,16);
|
||||
}
|
||||
|
||||
void TilePalette::paintEvent( QPaintEvent* )
|
||||
{
|
||||
QPainter p(this);
|
||||
for (int i=0; i<num; i++) {
|
||||
int x1 = width()*i/num;
|
||||
int x2 = width()*(i+1)/num;
|
||||
p.fillRect(x1,0,x2-x1,height(),QColor(rgb[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void TilePalette::mousePressEvent(QMouseEvent* e)
|
||||
{
|
||||
int c = e->x()*num/width();
|
||||
emit pick(rgb[c]);
|
||||
}
|
||||
|
||||
TileEditor::TileEditor(QWidget* parent) :
|
||||
QVBox(parent),
|
||||
editor(this),
|
||||
palette(this)
|
||||
{
|
||||
connect( &palette, SIGNAL(pick(QRgb)),
|
||||
&editor, SLOT(setColor(QRgb)) );
|
||||
connect( &editor, SIGNAL(pick(QRgb)),
|
||||
&palette, SLOT(setColor(QRgb)) );
|
||||
connect( &editor, SIGNAL(edited(const QImage&)),
|
||||
this, SIGNAL(edited(const QImage&)) );
|
||||
}
|
||||
|
||||
void TileEditor::edit(const QImage& i)
|
||||
{
|
||||
editor.setImage(i);
|
||||
palette.setFromImage(i);
|
||||
}
|
||||
|
||||
const QImage& TileEditor::image() const
|
||||
{
|
||||
return editor.image();
|
||||
}
|
||||
|
||||
class Main : public QMainWindow {
|
||||
public:
|
||||
Main() :
|
||||
central(this),
|
||||
editor(¢ral),
|
||||
picker(¢ral)
|
||||
{
|
||||
QPopupMenu* file = new QPopupMenu(menuBar());
|
||||
file->insertItem("&Save", &picker, SLOT(save()), CTRL+Key_S);
|
||||
file->insertSeparator();
|
||||
file->insertItem("&Exit", qApp, SLOT(quit()), CTRL+Key_Q);
|
||||
menuBar()->insertItem("&File", file);
|
||||
|
||||
connect( &picker, SIGNAL(pick(const QImage&)),
|
||||
&editor, SLOT(edit(const QImage&)) );
|
||||
connect( &picker, SIGNAL(pickName(const QString&)),
|
||||
statusBar(), SLOT(message(const QString&)) );
|
||||
connect( &editor, SIGNAL(edited(const QImage&)),
|
||||
&picker, SLOT(setCurrent(const QImage&)) );
|
||||
|
||||
setCentralWidget(¢ral);
|
||||
}
|
||||
|
||||
private:
|
||||
QHBox central;
|
||||
TileEditor editor;
|
||||
TilePicker picker;
|
||||
};
|
||||
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
QApplication app(argc,argv);
|
||||
Main m;
|
||||
app.setMainWidget(&m);
|
||||
m.show();
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
#include "tileedit.moc"
|
||||
Reference in New Issue
Block a user