200 lines
6.3 KiB
C++
200 lines
6.3 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2009 by Stefan Bühler *
|
|
* stbuehler@web.de *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
#include "piecelibrary.h"
|
|
|
|
#include <QPainter>
|
|
#include <QResource>
|
|
|
|
#include <lib3ds/io.h>
|
|
#include <lib3ds/mesh.h>
|
|
|
|
#include <GL/gl.h>
|
|
|
|
namespace toruschess {
|
|
typedef Lib3dsBool (*Lib3dsIoErrorFunc)(void *self);
|
|
typedef long (*Lib3dsIoSeekFunc)(void *self, long offset, Lib3dsIoSeek origin);
|
|
typedef long (*Lib3dsIoTellFunc)(void *self);
|
|
typedef size_t (*Lib3dsIoReadFunc)(void *self, void *buffer, size_t size);
|
|
typedef size_t (*Lib3dsIoWriteFunc)(void *self, const void *buffer, size_t size);
|
|
|
|
Lib3dsBool io3ds_error(void *self);
|
|
long io3ds_seek(void *self, long offset, Lib3dsIoSeek origin);
|
|
long io3ds_tell(void *self);
|
|
size_t io3ds_read(void *self, void *buffer, size_t size);
|
|
size_t io3ds_write(void *self, const void *buffer, size_t size);
|
|
|
|
class IO3ds {
|
|
public:
|
|
IO3ds(const QByteArray &data) : m_data(data), m_offset(0) {
|
|
m_io = lib3ds_io_new(this, io3ds_error, io3ds_seek, io3ds_tell, io3ds_read, io3ds_write);
|
|
}
|
|
~IO3ds() {
|
|
lib3ds_io_free(m_io);
|
|
}
|
|
|
|
long seek(long offset, Lib3dsIoSeek origin) {
|
|
switch (origin) {
|
|
case LIB3DS_SEEK_SET:
|
|
m_offset = offset;
|
|
break;
|
|
case LIB3DS_SEEK_CUR:
|
|
m_offset += offset;
|
|
break;
|
|
case LIB3DS_SEEK_END:
|
|
m_offset = m_data.length() + offset;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
long tell() { return m_offset; }
|
|
size_t read(void *buffer, size_t size) {
|
|
qDebug("read (size %i): data-len = %i, offset = %i", (int) size, m_data.length(), (int) m_offset);
|
|
if (m_offset >= m_data.length()) return 0;
|
|
size_t r = qMin(size, (size_t) m_data.length() - m_offset);
|
|
memcpy(buffer, m_data.constData() + m_offset, r);
|
|
m_offset += r;
|
|
qDebug("read: done with %i", (int) r);
|
|
return r;
|
|
}
|
|
size_t write(const void *, size_t ) {
|
|
return 0;
|
|
}
|
|
Lib3dsBool error() {
|
|
qDebug("3ds error");
|
|
return true;
|
|
}
|
|
|
|
Lib3dsIo* io() { return m_io; }
|
|
|
|
private:
|
|
Lib3dsIo *m_io;
|
|
QByteArray m_data;
|
|
long m_offset;
|
|
};
|
|
|
|
Lib3dsBool io3ds_error(void *self) {
|
|
IO3ds *s = (IO3ds*) self;
|
|
return s->error();
|
|
}
|
|
long io3ds_seek(void *self, long offset, Lib3dsIoSeek origin) {
|
|
IO3ds *s = (IO3ds*) self;
|
|
return s->seek(offset, origin);
|
|
}
|
|
long io3ds_tell(void *self) {
|
|
IO3ds *s = (IO3ds*) self;
|
|
return s->tell();
|
|
}
|
|
size_t io3ds_read(void *self, void *buffer, size_t size) {
|
|
IO3ds *s = (IO3ds*) self;
|
|
return s->read(buffer, size);
|
|
}
|
|
size_t io3ds_write(void *self, const void *buffer, size_t size) {
|
|
IO3ds *s = (IO3ds*) self;
|
|
return s->write(buffer, size);
|
|
}
|
|
|
|
|
|
Lib3dsFile *read_3ds(const QByteArray &data) {
|
|
return lib3ds_file_load("media/pawn.3ds");
|
|
IO3ds io(data);
|
|
Lib3dsFile *f = lib3ds_file_new();
|
|
if (!lib3ds_file_read(f, io.io())) {
|
|
qDebug("data size: %i", (int) data.size());
|
|
lib3ds_file_free(f);
|
|
return NULL;
|
|
}
|
|
return f;
|
|
}
|
|
|
|
QByteArray loadResource(const QString &filename) {
|
|
QResource res(filename);
|
|
qDebug("res size: %i", (int) res.size());
|
|
return QByteArray((const char*) res.data(), (int) res.size());
|
|
}
|
|
|
|
|
|
PieceLibrary::PieceLibrary(QObject *parent)
|
|
: QObject(parent), m_pieces(0), m_buffers(0) {
|
|
m_board = new QImage*[2];
|
|
m_board[0] = new QImage(":/media/board2_white.png");
|
|
m_board[1] = new QImage(":/media/board2_dark.png");
|
|
m_pawn = read_3ds(loadResource(":/media/pawn.3ds"));
|
|
setSize(45, 45);
|
|
}
|
|
|
|
PieceLibrary::~PieceLibrary() {
|
|
if (m_pawn) lib3ds_file_free(m_pawn);
|
|
delete [] m_pieces;
|
|
delete [] m_buffers;
|
|
delete [] m_board;
|
|
}
|
|
|
|
void PieceLibrary::setSize(int width, int height) {
|
|
m_width = qMax(10, width);
|
|
m_height = qMax(10, height);
|
|
if (m_buffers) {
|
|
for (int i = 0; i < 12; i++) {
|
|
delete m_buffers[i];
|
|
}
|
|
} else {
|
|
m_pieces = new QSvgRenderer* [12];
|
|
m_buffers = new QImage* [12];
|
|
for (int i = 0; i < 12; i++) {
|
|
m_pieces[i] = new QSvgRenderer(QString(":/media/chess_%1.svg").arg(i+1), this);
|
|
}
|
|
}
|
|
for (int i = 0; i < 12; i++) {
|
|
m_buffers[i] = new QImage(QSize(m_width, m_height), QImage::Format_ARGB32_Premultiplied);
|
|
m_buffers[i]->fill(0x0);
|
|
QPainter p(m_buffers[i]);
|
|
m_pieces[i]->render(&p);
|
|
}
|
|
}
|
|
|
|
void PieceLibrary::paint(QPainter &pt, int place) const {
|
|
if (place == 0) return;
|
|
if (place < 0) place = 6 - place;
|
|
if (place <= 0 || place > 12) return;
|
|
pt.drawImage(0, 0, *m_buffers[place-1]);
|
|
}
|
|
|
|
void PieceLibrary::paint(QPainter &pt, int place, const QRect &rect) const {
|
|
if (place == 0) return;
|
|
if (place < 0) place = 6 - place;
|
|
if (place <= 0 || place > 12) return;
|
|
pt.drawImage(rect, *m_buffers[place-1]);
|
|
}
|
|
|
|
void PieceLibrary::paint_board(QPainter &pt, bool darkField, const QRect &rect) const {
|
|
pt.drawImage(rect, *m_board[darkField ? 1 : 0]);
|
|
}
|
|
|
|
void PieceLibrary::paint_pawn() {
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(3,GL_FLOAT,0,m_pawn->meshes->pointL);
|
|
for (unsigned int i = 0; i < m_pawn->meshes->faces; i++) {
|
|
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, m_pawn->meshes->faceL[i].points);
|
|
}
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
}
|
|
|
|
}
|