yacreader/common/yacreader_flow_gl.cpp
Luis Ángel San Martín 047457da93 a?adida opci?n vsync (problema de rendimiento en modo de ventana)
corregido bug en la gesti?n de eventos de teclado de goToFlow

el nombre del fichero de c?mics se muestra ahora en el t?tulo de la ventana de
YACReader
2012-10-15 18:30:12 +02:00

1397 lines
35 KiB
C++
Raw Blame History

#include "yacreader_flow_gl.h"
#include <QtGui>
#include <QtOpenGL>
#include <math.h>
#include <gl/GLU.h>
#include <QGLContext>
#include <QGLPixelBuffer>
/*** Animation Settings ***/
/*** Position Configuration ***/
struct Preset defaultYACReaderFlowConfig = {
0.08f, //Animation_step sets the speed of the animation
1.5f, //Animation_speedup sets the acceleration of the animation
0.1f, //Animation_step_max sets the maximum speed of the animation
3.f, //Animation_Fade_out_dis sets the distance of view
1.5f, //pre_rotation sets the rotation increasion
3.f, //View_rotate_light_strenght sets the light strenght on rotation
0.01f, //View_rotate_add sets the speed of the rotation
0.02f, //View_rotate_sub sets the speed of reversing the rotation
20.f, //View_angle sets the maximum view angle
0.f, //CF_X the X Position of the Coverflow
0.f, //CF_Y the Y Position of the Coverflow
-12.f, //CF_Z the Z Position of the Coverflow
15.f, //CF_RX the X Rotation of the Coverflow
0.f, //CF_RY the Y Rotation of the Coverflow
0.f, //CF_RZ the Z Rotation of the Coverflow
-50.f, //Rotation sets the rotation of each cover
0.18f, //X_Distance sets the distance between the covers
1.f, //Center_Distance sets the distance between the centered and the non centered covers
0.1f, //Z_Distance sets the pushback amount
0.0f, //Y_Distance sets the elevation amount
30.f //zoom level
};
struct Preset presetYACReaderFlowClassicConfig = {
0.08f, //Animation_step sets the speed of the animation
1.5f, //Animation_speedup sets the acceleration of the animation
0.1f, //Animation_step_max sets the maximum speed of the animation
2.f, //Animation_Fade_out_dis sets the distance of view
1.5f, //pre_rotation sets the rotation increasion
3.f, //View_rotate_light_strenght sets the light strenght on rotation
0.08f, //View_rotate_add sets the speed of the rotation
0.08f, //View_rotate_sub sets the speed of reversing the rotation
30.f, //View_angle sets the maximum view angle
0.f, //CF_X the X Position of the Coverflow
-0.2f, //CF_Y the Y Position of the Coverflow
-7.f, //CF_Z the Z Position of the Coverflow
0.f, //CF_RX the X Rotation of the Coverflow
0.f, //CF_RY the Y Rotation of the Coverflow
0.f, //CF_RZ the Z Rotation of the Coverflow
-40.f, //Rotation sets the rotation of each cover
0.18f, //X_Distance sets the distance between the covers
1.f, //Center_Distance sets the distance between the centered and the non centered covers
0.1f, //Z_Distance sets the pushback amount
0.0f, //Y_Distance sets the elevation amount
22.f //zoom level
};
struct Preset presetYACReaderFlowStripeConfig = {
0.08f, //Animation_step sets the speed of the animation
1.5f, //Animation_speedup sets the acceleration of the animation
0.1f, //Animation_step_max sets the maximum speed of the animation
6.f, //Animation_Fade_out_dis sets the distance of view
1.5f, //pre_rotation sets the rotation increasion
4.f, //View_rotate_light_strenght sets the light strenght on rotation
0.08f, //View_rotate_add sets the speed of the rotation
0.08f, //View_rotate_sub sets the speed of reversing the rotation
30.f, //View_angle sets the maximum view angle
0.f, //CF_X the X Position of the Coverflow
-0.2f, //CF_Y the Y Position of the Coverflow
-7.f, //CF_Z the Z Position of the Coverflow
0.f, //CF_RX the X Rotation of the Coverflow
0.f, //CF_RY the Y Rotation of the Coverflow
0.f, //CF_RZ the Z Rotation of the Coverflow
0.f, //Rotation sets the rotation of each cover
1.1f, //X_Distance sets the distance between the covers
0.2f, //Center_Distance sets the distance between the centered and the non centered covers
0.01f, //Z_Distance sets the pushback amount
0.0f, //Y_Distance sets the elevation amount
22.f //zoom level
};
struct Preset presetYACReaderFlowOverlappedStripeConfig = {
0.08f, //Animation_step sets the speed of the animation
1.5f, //Animation_speedup sets the acceleration of the animation
0.1f, //Animation_step_max sets the maximum speed of the animation
2.f, //Animation_Fade_out_dis sets the distance of view
1.5f, //pre_rotation sets the rotation increasion
3.f, //View_rotate_light_strenght sets the light strenght on rotation
0.08f, //View_rotate_add sets the speed of the rotation
0.08f, //View_rotate_sub sets the speed of reversing the rotation
30.f, //View_angle sets the maximum view angle
0.f, //CF_X the X Position of the Coverflow
-0.2f, //CF_Y the Y Position of the Coverflow
-7.f, //CF_Z the Z Position of the Coverflow
0.f, //CF_RX the X Rotation of the Coverflow
0.f, //CF_RY the Y Rotation of the Coverflow
0.f, //CF_RZ the Z Rotation of the Coverflow
0.f, //Rotation sets the rotation of each cover
0.18f, //X_Distance sets the distance between the covers
1.f, //Center_Distance sets the distance between the centered and the non centered covers
0.1f, //Z_Distance sets the pushback amount
0.0f, //Y_Distance sets the elevation amount
22.f //zoom level
};
struct Preset pressetYACReaderFlowUpConfig = {
0.08f, //Animation_step sets the speed of the animation
1.5f, //Animation_speedup sets the acceleration of the animation
0.1f, //Animation_step_max sets the maximum speed of the animation
2.5f, //Animation_Fade_out_dis sets the distance of view
1.5f, //pre_rotation sets the rotation increasion
3.f, //View_rotate_light_strenght sets the light strenght on rotation
0.08f, //View_rotate_add sets the speed of the rotation
0.08f, //View_rotate_sub sets the speed of reversing the rotation
5.f, //View_angle sets the maximum view angle
0.f, //CF_X the X Position of the Coverflow
-0.2f, //CF_Y the Y Position of the Coverflow
-7.f, //CF_Z the Z Position of the Coverflow
0.f, //CF_RX the X Rotation of the Coverflow
0.f, //CF_RY the Y Rotation of the Coverflow
0.f, //CF_RZ the Z Rotation of the Coverflow
-50.f, //Rotation sets the rotation of each cover
0.18f, //X_Distance sets the distance between the covers
1.f, //Center_Distance sets the distance between the centered and the non centered covers
0.1f, //Z_Distance sets the pushback amount
-0.1f, //Y_Distance sets the elevation amount
22.f //zoom level
};
struct Preset pressetYACReaderFlowDownConfig = {
0.08f, //Animation_step sets the speed of the animation
1.5f, //Animation_speedup sets the acceleration of the animation
0.1f, //Animation_step_max sets the maximum speed of the animation
2.5f, //Animation_Fade_out_dis sets the distance of view
1.5f, //pre_rotation sets the rotation increasion
3.f, //View_rotate_light_strenght sets the light strenght on rotation
0.08f, //View_rotate_add sets the speed of the rotation
0.08f, //View_rotate_sub sets the speed of reversing the rotation
5.f, //View_angle sets the maximum view angle
0.f, //CF_X the X Position of the Coverflow
-0.2f, //CF_Y the Y Position of the Coverflow
-7.f, //CF_Z the Z Position of the Coverflow
0.f, //CF_RX the X Rotation of the Coverflow
0.f, //CF_RY the Y Rotation of the Coverflow
0.f, //CF_RZ the Z Rotation of the Coverflow
-50.f, //Rotation sets the rotation of each cover
0.18f, //X_Distance sets the distance between the covers
1.f, //Center_Distance sets the distance between the centered and the non centered covers
0.1f, //Z_Distance sets the pushback amount
0.1f, //Y_Distance sets the elevation amount
22.f //zoom level
};
/*Constructor*/
YACReaderFlowGL::YACReaderFlowGL(QWidget *parent,struct Preset p)
:QGLWidget(QGLFormat(QGL::SampleBuffers), parent),numObjects(0),lazyPopulateObjects(-1),bUseVSync(false)
{
updateCount = 0;
config = p;
currentSelected = 0;
centerPos.x = 0.f;
centerPos.y = 0.f;
centerPos.z = 1.f;
centerPos.rot = 0.f;
/*** Style ***/
shadingTop = 0.8f;
shadingBottom = 0.02f;
reflectionUp = 0.f;
reflectionBottom = 0.6f;
/*** System variables ***/
numObjects = 0;
//CFImage Dummy;
viewRotate = 0.f;
viewRotateActive = 0;
stepBackup = config.animationStep/config.animationSpeedUp;
/*QTimer * timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(updateImageData()));
timer->start(70);
*/
/*loader = new WidgetLoader(0,this);
loader->flow = this;
QThread * loaderThread = new QThread(parent);
loader->moveToThread(loaderThread);
loaderThread->start();*/
timerId = startTimer(16);
}
void YACReaderFlowGL::timerEvent(QTimerEvent * event)
{
if(timerId == event->timerId())
update();
//if(!worker->isRunning())
//worker->start();
}
YACReaderFlowGL::~YACReaderFlowGL()
{
}
QSize YACReaderFlowGL::minimumSizeHint() const
{
return QSize(800, 480);
}
QSize YACReaderFlowGL::sizeHint() const
{
return QSize(800, 480);
}
void YACReaderFlowGL::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
defaultTexture = bindTexture(QImage(":/images/defaultCover.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
markTexture = bindTexture(QImage(":/images/setRead.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
if(lazyPopulateObjects!=-1)
populate(lazyPopulateObjects);
}
void YACReaderFlowGL::paintGL()
{
/*glClearDepth(1.0);
glClearColor(1,1,1,1);*/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*glLoadIdentity();
glTranslatef(0.0, 0.0, -10.0);
glPopMatrix();*/
if(numObjects>0)
{
updatePositions();
draw();
}
}
void YACReaderFlowGL::resizeGL(int width, int height)
{
fontSize = width * 0.02;
//int side = qMin(width, height);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#ifdef QT_OPENGL_ES_1
//glOrthof(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
#else
//float sideX = ((float(width)/height)/2)*1.5;
//float sideY = 0.5*1.5;
gluPerspective(20.0, (float)width / (float)height, 1.0, 200.0);
//glOrtho(-sideX, sideX, -sideY+0.2, +sideY+0.2, 4, 11.0);
#endif
glMatrixMode(GL_MODELVIEW);
if(numObjects>0)
updatePositions();
}
//-----------------------------------------------------------------------------
/*Private*/
void YACReaderFlowGL::calcPos(CFImage *CF,int pos)
{
if(pos == 0){
CF->current = centerPos;
}else{
if(pos > 0){
CF->current.x = (config.centerDistance)+(config.xDistance*pos);
CF->current.y = config.yDistance*pos*-1;
CF->current.z = config.zDistance*pos*-1;
CF->current.rot = config.rotation;
}else{
CF->current.x = (config.centerDistance)*-1+(config.xDistance*pos);
CF->current.y = config.yDistance*pos;
CF->current.z = config.zDistance*pos;
CF->current.rot = config.rotation*-1;
}
}
}
void YACReaderFlowGL::calcRV(RVect *RV,int pos)
{
calcPos(&dummy,pos);
RV->x = dummy.current.x;
RV->y = dummy.current.y;
RV->z = dummy.current.z;
RV->rot = dummy.current.rot;
}
void YACReaderFlowGL::animate(RVect *Current,RVect to)
{
//calculate and apply positions
Current->x = Current->x+(to.x-Current->x)*config.animationStep;
Current->y = Current->y+(to.y-Current->y)*config.animationStep;
Current->z = Current->z+(to.z-Current->z)*config.animationStep;
if(abs(to.rot-Current->rot) > 0.01){
Current->rot = Current->rot+(to.rot-Current->rot)*(config.animationStep*config.preRotation);
}
else
viewRotateActive = 0;
}
void YACReaderFlowGL::drawCover(CFImage *CF)
{
float w = CF->width;
float h = CF->height;
//fadeout
float opacity = 1-1/(config.animationFadeOutDist+config.viewRotateLightStrenght*abs(viewRotate))*abs(0-CF->current.x);
glLoadIdentity();
glTranslatef(config.cfX,config.cfY,config.cfZ);
glRotatef(config.cfRX,1,0,0);
glRotatef(viewRotate*config.viewAngle+config.cfRY,0,1,0);
glRotatef(config.cfRZ,0,0,1);
glTranslatef( CF->current.x, CF->current.y, CF->current.z );
glPushMatrix();
glRotatef(CF->current.rot,0,1,0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, CF->img);
//calculate shading
float LShading = ((config.rotation != 0 )?((CF->current.rot < 0)?1-1/config.rotation*CF->current.rot:1):1);
float RShading = ((config.rotation != 0 )?((CF->current.rot > 0)?1-1/(config.rotation*-1)*CF->current.rot:1):1);
float LUP = shadingTop+(1-shadingTop)*LShading;
float LDOWN = shadingBottom+(1-shadingBottom)*LShading;
float RUP = shadingTop+(1-shadingTop)*RShading;
float RDOWN = shadingBottom+(1-shadingBottom)*RShading;;
//DrawCover
glBegin(GL_QUADS);
//esquina inferior izquierda
glColor4f(LDOWN*opacity,LDOWN*opacity,LDOWN*opacity,1);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(w/2.f*-1.f, -0.5f, 0.f);
//esquina inferior derecha
glColor4f(RDOWN*opacity,RDOWN*opacity,RDOWN*opacity,1);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(w/2.f, -0.5f, 0.f);
//esquina superior derecha
glColor4f(RUP*opacity,RUP*opacity,RUP*opacity,1);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(w/2.f, -0.5f+h, 0.f);
//esquina superior izquierda
glColor4f(LUP*opacity,LUP*opacity,LUP*opacity,1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(w/2.f*-1.f, -0.5f+h, 0.f);
glEnd();
//Draw reflection
glBegin(GL_QUADS);
//esquina inferior izquierda
glColor4f(LUP*opacity*reflectionUp,LUP*opacity*reflectionUp,LUP*opacity*reflectionUp,opacity*reflectionUp);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(w/2.f*-1.f, -0.5f-h, 0.f);
//esquina inferior derecha
glTexCoord2f(1.0f, 0.0f);
glVertex3f(w/2.f, -0.5f-h, 0.f);
//esquina superior derecha
glColor4f(opacity*reflectionBottom,opacity*reflectionBottom,opacity*reflectionBottom,opacity*reflectionBottom);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(w/2.f, -0.5f, 0.f);
//esquina superior izquierda
glTexCoord2f(0.0f, 1.0f);
glVertex3f(w/2.f*-1.f, -0.5f, 0.f);
glEnd();
glDisable(GL_TEXTURE_2D);
if(showMarks && loaded[CF->index] && marks[CF->index])
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, markTexture);
glBegin(GL_QUADS);
//esquina inferior izquierda
glColor4f(LDOWN*opacity,LDOWN*opacity,LDOWN*opacity,1);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(w/2.f-0.2f, -0.5f, 0.0001f);
//esquina inferior derecha
glColor4f(RDOWN*opacity,RDOWN*opacity,RDOWN*opacity,1);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(w/2.f, -0.5f, 0.0001f);
//esquina superior derecha
glColor4f(RUP*opacity,RUP*opacity,RUP*opacity,1);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(w/2.f, -0.3f, 0.0001f);
//esquina superior izquierda
glColor4f(LUP*opacity,LUP*opacity,LUP*opacity,1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(w/2.f-0.2f, -0.3f, 0.0001f);
glEnd();
glDisable(GL_TEXTURE_2D);
}
glPopMatrix();
}
/*Public*/
void YACReaderFlowGL::cleanupAnimation()
{
config.animationStep = stepBackup;
viewRotateActive = 0;
}
void YACReaderFlowGL::draw()
{
int CS = currentSelected;
int count;
//Draw right Covers
for(count = numObjects-1;count > -1;count--){
if(count > CS){
drawCover(&cfImages[count]);
}
}
//Draw left Covers
for(count = 0;count < numObjects-1;count++){
if(count < CS){
drawCover(&cfImages[count]);
}
}
//Draw Center Cover
drawCover(&cfImages[CS]);
//glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(-(float(width())/height())/2.0,(float(width())/height())/2.0, 0, 1, -10, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin( GL_TRIANGLES );
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glVertex2f( -0.03f, 0.98f);
glVertex2f( 0.03f, 0.98f);
glVertex2f( 0.f, 0.949f);
glEnd();
renderText(10, fontSize + 10,QString("%1/%2").arg(currentSelected+1).arg(numObjects),QFont("Arial", fontSize));
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
void YACReaderFlowGL::showPrevious()
{
if(currentSelected > 0){
currentSelected--;
emit centerIndexChanged(currentSelected);
config.animationStep *= config.animationSpeedUp;
if(config.animationStep > config.animationStepMax){
config.animationStep = config.animationStepMax;
}
if(viewRotateActive && viewRotate > -1){
viewRotate -= config.viewRotateAdd;
}
viewRotateActive = 1;
}
}
void YACReaderFlowGL::showNext()
{
if(currentSelected < numObjects-1){
currentSelected++;
emit centerIndexChanged(currentSelected);
config.animationStep *= config.animationSpeedUp;
if(config.animationStep > config.animationStepMax){
config.animationStep = config.animationStepMax;
}
if(viewRotateActive && viewRotate < 1){
viewRotate += config.viewRotateAdd;
}
viewRotateActive = 1;
}
}
void YACReaderFlowGL::setCurrentIndex(int pos)
{
currentSelected = pos;
config.animationStep *= config.animationSpeedUp;
if(config.animationStep > config.animationStepMax){
config.animationStep = config.animationStepMax;
}
if(viewRotateActive && viewRotate < 1){
viewRotate += config.viewRotateAdd;
}
viewRotateActive = 1;
}
void YACReaderFlowGL::updatePositions()
{
int count;
for(count = numObjects-1;count > -1;count--){
calcRV(&cfImages[count].animEnd,count-currentSelected);
animate(&cfImages[count].current,cfImages[count].animEnd);
}
//slowly reset view angle
if(!viewRotateActive){
viewRotate += (0-viewRotate)*config.viewRotateSub;
}
if(abs (cfImages[currentSelected].current.x - cfImages[currentSelected].animEnd.x) < 1)//viewRotate < 0.2)
{
cleanupAnimation();
if(updateCount >= 0) //TODO parametrizar
{
updateCount = 0;
updateImageData();
}
else
updateCount++;
}
else
updateCount++;
}
void YACReaderFlowGL::insert(char *name, GLuint Tex, float x, float y,int item)
{
//set a new entry
if(item == -1){
if(numObjects == 0){
cfImages = (CFImage*)malloc(sizeof(CFImage));
}
else
{
cfImages = (CFImage*)realloc(cfImages,(numObjects+1)*sizeof(CFImage));
}
item = numObjects;
numObjects++;
calcRV(&cfImages[item].current,item);
cfImages[item].current.x += 1;
cfImages[item].current.rot = 90;
}
cfImages[item].img = Tex;
cfImages[item].width = x;
cfImages[item].height = y;
cfImages[item].index = item;
strcpy(cfImages[item].name,name);
}
void YACReaderFlowGL::remove(int item)
{
//reposition current selection
if(item == currentSelected && currentSelected != 0){
currentSelected--;
}
int count = item;
while(count <= numObjects-2){
cfImages[count] = cfImages[count+1];
count++;
}
numObjects--;
cfImages = (CFImage*)realloc(cfImages,numObjects*sizeof(CFImage));
}
/*Info*/
CFImage YACReaderFlowGL::getCurrentSelected()
{
return cfImages[currentSelected];
}
void YACReaderFlowGL::replace(char *name, GLuint Tex, float x, float y,int item)
{
cfImages[item].img = Tex;
cfImages[item].width = x;
cfImages[item].height = y;
strcpy(cfImages[item].name,name);
loaded[item]=true;
}
void YACReaderFlowGL::populate(int n)
{
emit centerIndexChanged(0);
float x = 1;
float y = 1 * (700.f/480.0f);
int i;
for(i = 0;i<n;i++){
insert("cover", defaultTexture, x, y);
}
/*
for(int i = 0;i<n;i++){
QPixmap img = QPixmap(QString("./cover%1.jpg").arg(i+1));
GLuint cover = bindTexture(img, GL_TEXTURE_2D);
float y = 0.5 * (float(img.height())/img.width());
Insert("cover", cover, x, y);
}*/
loaded = QVector<bool>(n,false);
marks = QVector<bool>(n,false);
//worker->start();
}
void YACReaderFlowGL::reset()
{
currentSelected = 0;
loaded.clear();
for(int i = 0;i<numObjects;i++){
if(cfImages[i].img != defaultTexture)
deleteTexture(cfImages[i].img);
}
if(numObjects>0)
delete[] cfImages;
numObjects = 0;
}
void YACReaderFlowGL::reload()
{
int n = numObjects;
reset();
populate(n);
}
//slots
void YACReaderFlowGL::setCF_RX(int value)
{
config.cfRX = value;
}
void YACReaderFlowGL::setCF_RY(int value)
{
config.cfRY = value;
}
void YACReaderFlowGL::setCF_RZ(int value)
{
config.cfRZ = value;
}
void YACReaderFlowGL::setZoom(int zoom)
{
int width = this->width();
int height = this->height();
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//float sideX = ((float(width)/height)/2)*1.5;
//float sideY = 0.5*1.5;
gluPerspective(zoom, (float)width / (float)height, 1.0, 200.0);
//glOrtho(-sideX, sideX, -sideY+0.2, +sideY+0.2, 4, 11.0);
glMatrixMode(GL_MODELVIEW);
}
void YACReaderFlowGL::setRotation(int angle)
{
config.rotation = -angle;
}
//sets the distance between the covers
void YACReaderFlowGL::setX_Distance(int distance)
{
config.xDistance = distance/100.0;
}
//sets the distance between the centered and the non centered covers
void YACReaderFlowGL::setCenter_Distance(int distance)
{
config.centerDistance = distance/100.0;
}
//sets the pushback amount
void YACReaderFlowGL::setZ_Distance(int distance)
{
config.zDistance = distance/100.0;
}
void YACReaderFlowGL::setCF_Y(int value)
{
config.cfY = value/100.0;
}
void YACReaderFlowGL::setCF_Z(int value)
{
config.cfZ = value;
}
void YACReaderFlowGL::setY_Distance(int value)
{
config.yDistance = value / 100.0;
}
void YACReaderFlowGL::setFadeOutDist(int value)
{
config.animationFadeOutDist = value;
}
void YACReaderFlowGL::setLightStrenght(int value)
{
config.viewRotateLightStrenght = value;
}
void YACReaderFlowGL::setMaxAngle(int value)
{
config.viewAngle = value;
}
void YACReaderFlowGL::setPreset(const Preset & p)
{
config = p;
}
void YACReaderFlowGL::setPerformance(Performance performance)
{
if(this->performance != performance)
{
this->performance = performance;
reload();
}
}
void YACReaderFlowGL::useVSync(bool b)
{
if(bUseVSync != b)
{
bUseVSync = b;
if(b)
{
QGLFormat f = format();
f.setSwapInterval(1);
setFormat(f);
}
else
{
QGLFormat f = format();
f.setSwapInterval(0);
setFormat(f);
}
reload();
}
}
void YACReaderFlowGL::setShowMarks(bool value)
{
showMarks = value;
}
void YACReaderFlowGL::setMarks(QVector<bool> marks)
{
this->marks = marks;
}
void YACReaderFlowGL::setMarkImage(QImage & image)
{
//qu<71> pasa la primera vez??
//deleteTexture(markTexture);
//markTexture = bindTexture(image,GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
}
void YACReaderFlowGL::markSlide(int index)
{
marks[index] = true;
}
void YACReaderFlowGL::unmarkSlide(int index)
{
marks[index] = false;
}
void YACReaderFlowGL::setSlideSize(QSize size)
{
//TODO calcular el tama<6D>o del widget
}
void YACReaderFlowGL::clear()
{
reset();
}
void YACReaderFlowGL::setCenterIndex(int index)
{
setCurrentIndex(index);
}
void YACReaderFlowGL::showSlide(int index)
{
setCurrentIndex(index);
}
int YACReaderFlowGL::centerIndex()
{
return currentSelected;
}
void YACReaderFlowGL::updateMarks()
{
//do nothing
}
/*void YACReaderFlowGL::setFlowType(FlowType flowType)
{
//TODO esperar a que se reimplemente flowtype
}*/
void YACReaderFlowGL::render()
{
//do nothing
}
//EVENTOS
void YACReaderFlowGL::wheelEvent(QWheelEvent * event)
{
if(event->delta()<0)
showNext();
else
showPrevious();
event->accept();
}
void YACReaderFlowGL::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Left)
{
if(event->modifiers() == Qt::ControlModifier)
setCurrentIndex((currentSelected-10<0)?0:currentSelected-10);
else
showPrevious();
event->accept();
return;
}
if(event->key() == Qt::Key_Right)
{
if(event->modifiers() == Qt::ControlModifier)
setCurrentIndex((currentSelected+10>=numObjects)?numObjects-1:currentSelected+10);
else
showNext();
event->accept();
return;
}
event->ignore();
}
void YACReaderFlowGL::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
float x,y;
x = event->x();
y = event->y();
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble posX, posY, posZ;
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
winX = (float)x;
winY = (float)viewport[3] - (float)y;
glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
if(posX >= 0.5)
{
//int index = currentSelected+1;
//while((cfImages[index].current.x-cfImages[index].width/(2.0*config.rotation)) < posX)
// index++;
//setCurrentIndex(index-1);
showNext();
}
else if(posX <=-0.5)
showPrevious();
} else
QGLWidget::mousePressEvent(event);
}
void YACReaderFlowGL::mouseDoubleClickEvent(QMouseEvent* event)
{
emit selected(centerIndex());
event->accept();
}
YACReaderComicFlowGL::YACReaderComicFlowGL(QWidget *parent,struct Preset p )
:YACReaderFlowGL(parent,p)
{
worker = new ImageLoaderGL(this);
worker->flow = this;
}
void YACReaderComicFlowGL::setImagePaths(QStringList paths)
{
worker->reset();
reset();
numObjects = 0;
if(lazyPopulateObjects!=-1)
YACReaderFlowGL::populate(paths.size());
lazyPopulateObjects = paths.size();
this->paths = paths;
//numObjects = paths.size();
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void YACReaderComicFlowGL::updateImageData()
{
// can't do anything, wait for the next possibility
if(worker->busy())
return;
// set image of last one
int idx = worker->index();
if( idx >= 0 && !worker->result().isNull())
{
if(!loaded[idx])
{
float x = 1;
QImage img = worker->result();
GLuint cover;
if(performance == high || performance == ultraHigh)
cover = bindTexture(img, GL_TEXTURE_2D,GL_RGB,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
else
cover = bindTexture(img, GL_TEXTURE_2D,GL_RGB,QGLContext::LinearFilteringBindOption);
float y = 1 * (float(img.height())/img.width());
replace("cover", cover, x, y,idx);
/*CFImages[idx].width = x;
CFImages[idx].height = y;
CFImages[idx].img = worker->resultTexture;
strcpy(CFImages[idx].name,"cover");*/
loaded[idx] = true;
//numImagesLoaded++;
}
}
// try to load only few images on the left and right side
// i.e. all visible ones plus some extra
int count=8;
switch(performance)
{
case low:
count = 8;
break;
case medium:
count = 10;
break;
case high:
count = 12;
break;
case ultraHigh:
count = 14;
break;
}
int * indexes = new int[2*count+1];
int center = currentSelected;
indexes[0] = center;
for(int j = 0; j < count; j++)
{
indexes[j*2+1] = center+j+1;
indexes[j*2+2] = center-j-1;
}
for(int c = 0; c < 2*count+1; c++)
{
int i = indexes[c];
if((i >= 0) && (i < numObjects))
if(!loaded[i])//slide(i).isNull())
{
//loader->loadTexture(i);
//loaded[i]=true;
// schedule thumbnail generation
if(paths.size()>0)
{
QString fname = paths.at(i);
//loaded[i]=true;
worker->generate(i, fname);
}
delete[] indexes;
return;
}
}
}
YACReaderPageFlowGL::YACReaderPageFlowGL(QWidget *parent,struct Preset p )
:YACReaderFlowGL(parent,p)
{
worker = new ImageLoaderByteArrayGL(this);
worker->flow = this;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void YACReaderPageFlowGL::updateImageData()
{
// can't do anything, wait for the next possibility
if(worker->busy())
return;
// set image of last one
int idx = worker->index();
if( idx >= 0 && !worker->result().isNull())
{
if(!loaded[idx])
{
float x = 1;
QImage img = worker->result();
GLuint cover;
if(performance == high || performance == ultraHigh)
cover = bindTexture(img, GL_TEXTURE_2D,GL_RGB,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
else
cover = bindTexture(img, GL_TEXTURE_2D,GL_RGB,QGLContext::LinearFilteringBindOption);
float y = 1 * (float(img.height())/img.width());
replace("cover", cover, x, y,idx);
/*CFImages[idx].width = x;
CFImages[idx].height = y;
CFImages[idx].img = worker->resultTexture;
strcpy(CFImages[idx].name,"cover");*/
loaded[idx] = true;
//numImagesLoaded++;
}
}
// try to load only few images on the left and right side
// i.e. all visible ones plus some extra
int count=8;
switch(performance)
{
case low:
count = 8;
break;
case medium:
count = 10;
break;
case high:
count = 12;
break;
case ultraHigh:
count = 14;
break;
}
int * indexes = new int[2*count+1];
int center = currentSelected;
indexes[0] = center;
for(int j = 0; j < count; j++)
{
indexes[j*2+1] = center+j+1;
indexes[j*2+2] = center-j-1;
}
for(int c = 0; c < 2*count+1; c++)
{
int i = indexes[c];
if((i >= 0) && (i < numObjects))
if(rawImages.size()>0)
if(!loaded[i]&&imagesReady[i])//slide(i).isNull())
{
//loader->loadTexture(i);
//loaded[i]=true;
// schedule thumbnail generation
//loaded[i]=true;
worker->generate(i, rawImages.at(i));
delete[] indexes;
return;
}
}
}
void YACReaderPageFlowGL::populate(int n)
{
worker->reset();
if(lazyPopulateObjects!=-1)
YACReaderFlowGL::populate(n);
lazyPopulateObjects = n;
imagesReady = QVector<bool> (n,false);
rawImages = QVector<QByteArray> (n);
imagesSetted = QVector<bool> (n,false); //puede sobrar
}
//-----------------------------------------------------------------------------
//ImageLoader
//-----------------------------------------------------------------------------
QImage ImageLoaderGL::loadImage(const QString& fileName)
{
QImage image;
bool result = image.load(fileName);
switch(flow->performance)
{
case low:
image = image.scaledToWidth(200,Qt::SmoothTransformation);
break;
case medium:
image = image.scaledToWidth(256,Qt::SmoothTransformation);
break;
case high:
image = image.scaledToWidth(320,Qt::SmoothTransformation);
break;
}
if(!result)
return QImage();
return image;
}
ImageLoaderGL::ImageLoaderGL(YACReaderFlowGL * flow):
QThread(),flow(flow),restart(false), working(false), idx(-1)
{
}
ImageLoaderGL::~ImageLoaderGL()
{
mutex.lock();
condition.wakeOne();
mutex.unlock();
wait();
}
bool ImageLoaderGL::busy() const
{
return isRunning() ? working : false;
}
void ImageLoaderGL::generate(int index, const QString& fileName)
{
mutex.lock();
this->idx = index;
this->fileName = fileName;
this->size = size;
this->img = QImage();
mutex.unlock();
if (!isRunning())
start();
else
{
// already running, wake up whenever ready
restart = true;
condition.wakeOne();
}
}
void ImageLoaderGL::run()
{
for(;;)
{
// copy necessary data
mutex.lock();
this->working = true;
QString fileName = this->fileName;
mutex.unlock();
QImage image = loadImage(fileName);
// let everyone knows it is ready
mutex.lock();
this->working = false;
this->img = image;
mutex.unlock();
// put to sleep
mutex.lock();
if (!this->restart)
condition.wait(&mutex);
restart = false;
mutex.unlock();
}
}
QImage ImageLoaderGL::result()
{
return img;
}
//-----------------------------------------------------------------------------
//ImageLoader
//-----------------------------------------------------------------------------
QImage ImageLoaderByteArrayGL::loadImage(const QByteArray& raw)
{
QImage image;
bool result = image.loadFromData(raw);
switch(flow->performance)
{
case low:
image = image.scaledToWidth(128,Qt::SmoothTransformation);
break;
case medium:
image = image.scaledToWidth(196,Qt::SmoothTransformation);
break;
case high:
image = image.scaledToWidth(256,Qt::SmoothTransformation);
break;
case ultraHigh:
image = image.scaledToWidth(320,Qt::SmoothTransformation);
break;
}
if(!result)
return QImage();
return image;
}
ImageLoaderByteArrayGL::ImageLoaderByteArrayGL(YACReaderFlowGL * flow):
QThread(),flow(flow),restart(false), working(false), idx(-1)
{
}
ImageLoaderByteArrayGL::~ImageLoaderByteArrayGL()
{
mutex.lock();
condition.wakeOne();
mutex.unlock();
wait();
}
bool ImageLoaderByteArrayGL::busy() const
{
return isRunning() ? working : false;
}
void ImageLoaderByteArrayGL::generate(int index, const QByteArray& raw)
{
mutex.lock();
this->idx = index;
this->rawData = raw;
this->size = size;
this->img = QImage();
mutex.unlock();
if (!isRunning())
start();
else
{
// already running, wake up whenever ready
restart = true;
condition.wakeOne();
}
}
void ImageLoaderByteArrayGL::run()
{
for(;;)
{
// copy necessary data
mutex.lock();
this->working = true;
QByteArray raw = this->rawData;
mutex.unlock();
QImage image = loadImage(raw);
// let everyone knows it is ready
mutex.lock();
this->working = false;
this->img = image;
mutex.unlock();
// put to sleep
mutex.lock();
if (!this->restart)
condition.wait(&mutex);
restart = false;
mutex.unlock();
}
}
QImage ImageLoaderByteArrayGL::result()
{
return img;
}
//WidgetLoader::WidgetLoader(QWidget *parent, QGLWidget * shared)
// :QGLWidget(parent,shared)
//{
//}
//
//void WidgetLoader::loadTexture(int index)
//{
// QImage image;
// bool result = image.load(QString("./cover%1.jpg").arg(index+1));
// //image = image.scaledToWidth(128,Qt::SmoothTransformation); //TODO parametrizar
// flow->cfImages[index].width = 0.5;
// flow->cfImages[index].height = 0.5 * (float(image.height())/image.width());
// flow->cfImages[index].img = bindTexture(image, GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
//}