mirror of
				https://github.com/YACReader/yacreader
				synced 2025-11-03 16:54:39 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			1606 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1606 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "yacreader_flow_gl.h"
 | 
						|
 | 
						|
#include <QtGui>
 | 
						|
#include <QtOpenGL>
 | 
						|
//#include <math.h>
 | 
						|
 | 
						|
#ifdef Q_OS_MAC
 | 
						|
	#include <OpenGL/glu.h>
 | 
						|
#else
 | 
						|
	#include <GL/glu.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <QGLContext>
 | 
						|
#include <QGLPixelBuffer>
 | 
						|
#include <cmath>
 | 
						|
 | 
						|
/*** Animation Settings ***/
 | 
						|
 | 
						|
/*** Position Configuration ***/
 | 
						|
 | 
						|
int YACReaderFlowGL::updateInterval = 16;
 | 
						|
 | 
						|
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
 | 
						|
	-8.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),hasBeenInitialized(false),flowRightToLeft(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();*/
 | 
						|
 | 
						|
    /*QGLFormat f = format();
 | 
						|
    f.setVersion(2, 1);
 | 
						|
    f.setSwapInterval(0);
 | 
						|
    setFormat(f);*/
 | 
						|
 | 
						|
    timerId = startTimer(updateInterval);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::timerEvent(QTimerEvent * event)
 | 
						|
{
 | 
						|
	if(timerId == event->timerId())
 | 
						|
        updateGL();
 | 
						|
 | 
						|
	//if(!worker->isRunning())
 | 
						|
    //worker->start();
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::startAnimationTimer()
 | 
						|
{
 | 
						|
    if(timerId == -1)
 | 
						|
        timerId = startTimer(updateInterval);
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::stopAnimationTimer()
 | 
						|
{
 | 
						|
    if(timerId != -1)
 | 
						|
    {
 | 
						|
        killTimer(timerId);
 | 
						|
        timerId = -1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
YACReaderFlowGL::~YACReaderFlowGL()
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
QSize YACReaderFlowGL::minimumSizeHint() const
 | 
						|
{
 | 
						|
	return QSize(320, 200);
 | 
						|
}
 | 
						|
 | 
						|
/*QSize YACReaderFlowGL::sizeHint() const
 | 
						|
{
 | 
						|
	return QSize(320, 200);
 | 
						|
}*/
 | 
						|
 | 
						|
void YACReaderFlowGL::initializeGL()
 | 
						|
{
 | 
						|
	glEnable(GL_DEPTH_TEST);
 | 
						|
    glEnable(GL_CULL_FACE);
 | 
						|
	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/readRibbon.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
 | 
						|
	readingTexture = bindTexture(QImage(":/images/readingRibbon.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
 | 
						|
	if(lazyPopulateObjects!=-1)
 | 
						|
		populate(lazyPopulateObjects);
 | 
						|
 | 
						|
	hasBeenInitialized = true;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::paintGL()
 | 
						|
{
 | 
						|
    /*glClearDepth(1.0);*/
 | 
						|
    glClearColor(0,0,0,1);
 | 
						|
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
						|
	/*glLoadIdentity();
 | 
						|
	glTranslatef(0.0, 0.0, -10.0);
 | 
						|
	glPopMatrix();*/
 | 
						|
	if(numObjects>0)
 | 
						|
	{
 | 
						|
		updatePositions();
 | 
						|
		udpatePerspective(width(),height());
 | 
						|
		draw();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::resizeGL(int width, int height)
 | 
						|
{
 | 
						|
    float pixelRatio = devicePixelRatio();
 | 
						|
    fontSize = (width + height) * 0.010 * pixelRatio;
 | 
						|
	if(fontSize < 10)
 | 
						|
		fontSize = 10;
 | 
						|
 | 
						|
	//int side = qMin(width, height);
 | 
						|
	udpatePerspective(width,height);
 | 
						|
 | 
						|
	if(numObjects>0)
 | 
						|
		updatePositions();
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::udpatePerspective(int width, int height)
 | 
						|
{
 | 
						|
    float pixelRatio = devicePixelRatio();
 | 
						|
    glViewport(0, 0, width*pixelRatio, height*pixelRatio);
 | 
						|
 | 
						|
	glMatrixMode(GL_PROJECTION);
 | 
						|
	glLoadIdentity();
 | 
						|
 | 
						|
	gluPerspective(20.0, GLdouble(width) / (float)height, 1.0, 200.0);
 | 
						|
 | 
						|
	glMatrixMode(GL_MODELVIEW);
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
/*Private*/
 | 
						|
void YACReaderFlowGL::calcPos(YACReader3DImage & image, int pos)
 | 
						|
{
 | 
						|
		if(flowRightToLeft){
 | 
						|
				pos = pos * -1;
 | 
						|
		}
 | 
						|
    if(pos == 0){
 | 
						|
        image.current = centerPos;
 | 
						|
    }else{
 | 
						|
        if(pos > 0){
 | 
						|
            image.current.x = (config.centerDistance)+(config.xDistance*pos);
 | 
						|
            image.current.y = config.yDistance*pos*-1;
 | 
						|
            image.current.z = config.zDistance*pos*-1;
 | 
						|
            image.current.rot = config.rotation;
 | 
						|
        }else{
 | 
						|
            image.current.x = (config.centerDistance)*-1+(config.xDistance*pos);
 | 
						|
            image.current.y =  config.yDistance*pos;
 | 
						|
            image.current.z = config.zDistance*pos;
 | 
						|
            image.current.rot = config.rotation*-1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
void YACReaderFlowGL::calcVector(YACReader3DVector & vector, int pos)
 | 
						|
{
 | 
						|
    calcPos(dummy,pos);
 | 
						|
 | 
						|
    vector.x = dummy.current.x;
 | 
						|
    vector.y = dummy.current.y;
 | 
						|
    vector.z = dummy.current.z;
 | 
						|
    vector.rot = dummy.current.rot;
 | 
						|
}
 | 
						|
 | 
						|
bool YACReaderFlowGL::animate(YACReader3DVector & currentVector,YACReader3DVector & toVector)
 | 
						|
{
 | 
						|
    float rotDiff = toVector.rot-currentVector.rot;
 | 
						|
    float xDiff = toVector.x-currentVector.x;
 | 
						|
    float yDiff = toVector.y-currentVector.y;
 | 
						|
    float zDiff = toVector.z-currentVector.z;
 | 
						|
 | 
						|
    if(fabs(rotDiff) < 0.01
 | 
						|
       && fabs(xDiff)  < 0.001
 | 
						|
       && fabs(yDiff)  < 0.001
 | 
						|
       && fabs(zDiff)  < 0.001)
 | 
						|
        return true;
 | 
						|
 | 
						|
    //calculate and apply positions
 | 
						|
    currentVector.x = currentVector.x+(xDiff)*config.animationStep;
 | 
						|
    currentVector.y = currentVector.y+(yDiff)*config.animationStep;
 | 
						|
    currentVector.z = currentVector.z+(zDiff)*config.animationStep;
 | 
						|
 | 
						|
    if(fabs(rotDiff) > 0.01){
 | 
						|
        currentVector.rot = currentVector.rot+(rotDiff)*(config.animationStep*config.preRotation);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        viewRotateActive = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
void YACReaderFlowGL::drawCover(const YACReader3DImage & image)
 | 
						|
{
 | 
						|
    float w = image.width;
 | 
						|
    float h = image.height;
 | 
						|
 | 
						|
	//fadeout
 | 
						|
    float opacity = 1-1/(config.animationFadeOutDist+config.viewRotateLightStrenght*fabs(viewRotate))*fabs(0-image.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( image.current.x, image.current.y, image.current.z );
 | 
						|
 | 
						|
	glPushMatrix();
 | 
						|
    glRotatef(image.current.rot,0,1,0);
 | 
						|
 | 
						|
	glEnable(GL_TEXTURE_2D);
 | 
						|
    glBindTexture(GL_TEXTURE_2D, image.texture);
 | 
						|
 | 
						|
	//calculate shading
 | 
						|
    float LShading = ((config.rotation != 0 )?((image.current.rot < 0)?1-1/config.rotation*image.current.rot:1):1);
 | 
						|
    float RShading = ((config.rotation != 0 )?((image.current.rot > 0)?1-1/(config.rotation*-1)*image.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/2,LUP*opacity*reflectionUp/2,LUP*opacity*reflectionUp/2,1);
 | 
						|
	glTexCoord2f(0.0f, 0.0f);
 | 
						|
	glVertex3f(w/2.f*-1.f, -0.5f-h, 0.f);
 | 
						|
 | 
						|
	//esquina inferior derecha
 | 
						|
    glColor4f(RUP*opacity*reflectionUp/2,RUP*opacity*reflectionUp/2,RUP*opacity*reflectionUp/2,1);
 | 
						|
	glTexCoord2f(1.0f, 0.0f);
 | 
						|
	glVertex3f(w/2.f, -0.5f-h, 0.f);
 | 
						|
 | 
						|
	//esquina superior derecha
 | 
						|
    glColor4f(RDOWN*opacity/3,RDOWN*opacity/3,RDOWN*opacity/3,1);
 | 
						|
	glTexCoord2f(1.0f, 1.0f);
 | 
						|
	glVertex3f(w/2.f, -0.5f, 0.f);
 | 
						|
 | 
						|
	//esquina superior izquierda
 | 
						|
    glColor4f(LDOWN*opacity/3,LDOWN*opacity/3,LDOWN*opacity/3,1);
 | 
						|
	glTexCoord2f(0.0f, 1.0f);
 | 
						|
	glVertex3f(w/2.f*-1.f, -0.5f, 0.f);
 | 
						|
 | 
						|
	glEnd();
 | 
						|
	glDisable(GL_TEXTURE_2D);
 | 
						|
 | 
						|
    if(showMarks && loaded[image.index] && marks[image.index] != Unread)
 | 
						|
	{
 | 
						|
		glEnable(GL_TEXTURE_2D);
 | 
						|
        if(marks[image.index] == Read)
 | 
						|
			glBindTexture(GL_TEXTURE_2D, markTexture);
 | 
						|
		else
 | 
						|
			glBindTexture(GL_TEXTURE_2D, readingTexture);
 | 
						|
		glBegin(GL_QUADS);
 | 
						|
 | 
						|
		//esquina inferior izquierda
 | 
						|
		glColor4f(RUP*opacity,RUP*opacity,RUP*opacity,1);
 | 
						|
		glTexCoord2f(0.0f, 1.0f);
 | 
						|
        glVertex3f(w/2.f-0.2, -0.688f+h, 0.001f);
 | 
						|
 | 
						|
		//esquina inferior derecha
 | 
						|
        glColor4f(RUP*opacity,RUP*opacity,RUP*opacity,1);
 | 
						|
		glTexCoord2f(1.0f, 1.0f);
 | 
						|
        glVertex3f(w/2.f-0.05, -0.688f+h, 0.001f);
 | 
						|
 | 
						|
		//esquina superior derecha
 | 
						|
		glColor4f(RUP*opacity,RUP*opacity,RUP*opacity,1);
 | 
						|
		glTexCoord2f(1.0f, 0.0f);
 | 
						|
        glVertex3f(w/2.f-0.05, -0.488f+h, 0.001f);
 | 
						|
 | 
						|
		//esquina superior izquierda
 | 
						|
		glColor4f(RUP*opacity,RUP*opacity,RUP*opacity,1);
 | 
						|
		glTexCoord2f(0.0f, 0.0f);
 | 
						|
        glVertex3f(w/2.f-0.2, -0.488f+h, 0.001f);
 | 
						|
 | 
						|
		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(images[count]);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	//Draw left Covers
 | 
						|
	for(count = 0;count < numObjects-1;count++){
 | 
						|
		if(count < CS){
 | 
						|
            drawCover(images[count]);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	//Draw Center Cover
 | 
						|
    drawCover(images[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();
 | 
						|
 | 
						|
    glColor4f( 0.3f, 0.3f, 0.3f, 1.0f );
 | 
						|
 | 
						|
	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()
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	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()
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	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)
 | 
						|
{
 | 
						|
    if(!(pos>=0 && pos < images.length() && images.length()>0))
 | 
						|
        return;
 | 
						|
    if(pos >= images.length() && images.length() > 0)
 | 
						|
        pos = images.length()-1;
 | 
						|
 | 
						|
        startAnimationTimer();
 | 
						|
 | 
						|
        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;
 | 
						|
 | 
						|
    bool stopAnimation = true;
 | 
						|
    for(count = numObjects-1;count > -1;count--){
 | 
						|
        calcVector(images[count].animEnd,count-currentSelected);
 | 
						|
        if(!animate(images[count].current,images[count].animEnd))
 | 
						|
            stopAnimation = false;
 | 
						|
    }
 | 
						|
 | 
						|
    //slowly reset view angle
 | 
						|
    if(!viewRotateActive){
 | 
						|
        viewRotate += (0-viewRotate)*config.viewRotateSub;
 | 
						|
    }
 | 
						|
 | 
						|
    if(fabs (images[currentSelected].current.x - images[currentSelected].animEnd.x) < 1)//viewRotate < 0.2)
 | 
						|
    {
 | 
						|
        cleanupAnimation();
 | 
						|
        if(updateCount >= 0) //TODO parametrizar
 | 
						|
        {
 | 
						|
 | 
						|
            updateCount = 0;
 | 
						|
            updateImageData();
 | 
						|
        }
 | 
						|
        else
 | 
						|
            updateCount++;
 | 
						|
    }
 | 
						|
    else
 | 
						|
        updateCount++;
 | 
						|
 | 
						|
    if(stopAnimation)
 | 
						|
        stopAnimationTimer();
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::insert(const char *name, GLuint texture, float x, float y,int item)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
    Q_UNUSED(name)
 | 
						|
    //set a new entry
 | 
						|
    if(item == -1){
 | 
						|
        images.push_back(YACReader3DImage());
 | 
						|
 | 
						|
        item = numObjects;
 | 
						|
        numObjects++;
 | 
						|
 | 
						|
        calcVector(images[item].current,item);
 | 
						|
        images[item].current.z = images[item].current.z-1;
 | 
						|
    }
 | 
						|
 | 
						|
    images[item].texture = texture;
 | 
						|
    images[item].width = x;
 | 
						|
    images[item].height = y;
 | 
						|
    images[item].index = item;
 | 
						|
    //strcpy(cfImages[item].name,name);
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::remove(int item)
 | 
						|
{
 | 
						|
    if(item < 0 || item >= images.size())
 | 
						|
        return;
 | 
						|
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
    loaded.remove(item);
 | 
						|
    marks.remove(item);
 | 
						|
 | 
						|
    //reposition current selection
 | 
						|
    if(item <= currentSelected && currentSelected != 0){
 | 
						|
        currentSelected--;
 | 
						|
    }
 | 
						|
 | 
						|
    int count = item;
 | 
						|
    while(count <= numObjects-2){
 | 
						|
        images[count].index--;
 | 
						|
        count++;
 | 
						|
    }
 | 
						|
    images.removeAt(item);
 | 
						|
 | 
						|
 | 
						|
    numObjects--;
 | 
						|
}
 | 
						|
 | 
						|
/*Info*/
 | 
						|
YACReader3DImage YACReaderFlowGL::getCurrentSelected()
 | 
						|
{
 | 
						|
    return images[currentSelected];
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::replace(const char *name, GLuint texture, float x, float y,int item)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
    Q_UNUSED(name)
 | 
						|
    if(images[item].index == item)
 | 
						|
    {
 | 
						|
        images[item].texture = texture;
 | 
						|
        images[item].width = x;
 | 
						|
        images[item].height = y;
 | 
						|
        loaded[item]=true;
 | 
						|
    }
 | 
						|
    else
 | 
						|
        loaded[item]=false;
 | 
						|
}
 | 
						|
 | 
						|
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++){
 | 
						|
        QString s = "cover";
 | 
						|
        insert(s.toLocal8Bit().data(), 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()
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
    currentSelected = 0;
 | 
						|
    loaded.clear();
 | 
						|
 | 
						|
    for(int i = 0;i<numObjects;i++){
 | 
						|
        if(images[i].texture != defaultTexture)
 | 
						|
            deleteTexture(images[i].texture);
 | 
						|
    }
 | 
						|
 | 
						|
    numObjects = 0;
 | 
						|
    images.clear();
 | 
						|
 | 
						|
    if(!hasBeenInitialized)
 | 
						|
        lazyPopulateObjects = -1;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::reload()
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	int n = numObjects;
 | 
						|
	reset();
 | 
						|
	populate(n);
 | 
						|
}
 | 
						|
 | 
						|
//slots
 | 
						|
void YACReaderFlowGL::setCF_RX(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.cfRX = value;
 | 
						|
}
 | 
						|
void YACReaderFlowGL::setCF_RY(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.cfRY = value;
 | 
						|
}
 | 
						|
void YACReaderFlowGL::setCF_RZ(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.cfRZ = value;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setZoom(int zoom)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	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)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.rotation = -angle;
 | 
						|
}
 | 
						|
//sets the distance between the covers
 | 
						|
void YACReaderFlowGL::setX_Distance(int distance)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.xDistance = distance/100.0;
 | 
						|
}
 | 
						|
//sets the distance between the centered and the non centered covers
 | 
						|
void YACReaderFlowGL::setCenter_Distance(int distance)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.centerDistance = distance/100.0;
 | 
						|
}
 | 
						|
//sets the pushback amount
 | 
						|
void YACReaderFlowGL::setZ_Distance(int distance)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.zDistance = distance/100.0;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setCF_Y(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.cfY = value/100.0;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setCF_Z(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.cfZ = value;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setY_Distance(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.yDistance = value / 100.0;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setFadeOutDist(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
    config.animationFadeOutDist = value;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setLightStrenght(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
    config.viewRotateLightStrenght = value;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setMaxAngle(int value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config.viewAngle = value;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setPreset(const Preset & p)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	config = p;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setPerformance(Performance performance)
 | 
						|
{
 | 
						|
	if(this->performance != performance)
 | 
						|
	{
 | 
						|
        startAnimationTimer();
 | 
						|
 | 
						|
		this->performance = performance;
 | 
						|
		reload();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::useVSync(bool b)
 | 
						|
{/*if(bUseVSync != b)
 | 
						|
	{
 | 
						|
		bUseVSync = b;
 | 
						|
		if(b)
 | 
						|
		{
 | 
						|
			QGLFormat f = format();
 | 
						|
            //f.setVersion(2, 1);
 | 
						|
            f.setSwapInterval(1);
 | 
						|
			setFormat(f);
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			QGLFormat f = format();
 | 
						|
            //f.setVersion(2, 1);
 | 
						|
			f.setSwapInterval(0);
 | 
						|
			setFormat(f);
 | 
						|
		}
 | 
						|
        reset();
 | 
						|
    }*/
 | 
						|
}
 | 
						|
void YACReaderFlowGL::setShowMarks(bool value)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	showMarks = value;
 | 
						|
}
 | 
						|
void YACReaderFlowGL::setMarks(QVector<YACReaderComicReadStatus> marks)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	this->marks = marks;
 | 
						|
}
 | 
						|
void YACReaderFlowGL::setMarkImage(QImage & image)
 | 
						|
{
 | 
						|
	Q_UNUSED(image);
 | 
						|
	//qué pasa la primera vez??
 | 
						|
	//deleteTexture(markTexture);
 | 
						|
	//markTexture = bindTexture(image,GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption);
 | 
						|
}
 | 
						|
void YACReaderFlowGL::markSlide(int index, YACReaderComicReadStatus status)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	marks[index] = status;
 | 
						|
}
 | 
						|
void YACReaderFlowGL::unmarkSlide(int index)
 | 
						|
{
 | 
						|
    startAnimationTimer();
 | 
						|
 | 
						|
	marks[index] = YACReader::Unread;
 | 
						|
}
 | 
						|
void YACReaderFlowGL::setSlideSize(QSize size)
 | 
						|
{
 | 
						|
	Q_UNUSED(size);
 | 
						|
	//TODO calcular el tamaño del widget
 | 
						|
}
 | 
						|
void YACReaderFlowGL::clear()
 | 
						|
{
 | 
						|
	reset();
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setCenterIndex(unsigned 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
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::setFlowRightToLeft(bool b)
 | 
						|
{
 | 
						|
    flowRightToLeft = b;
 | 
						|
}
 | 
						|
 | 
						|
//EVENTOS
 | 
						|
void YACReaderFlowGL::wheelEvent(QWheelEvent * event)
 | 
						|
{
 | 
						|
    Movement m = getMovement(event);
 | 
						|
    switch (m) {
 | 
						|
    case None:
 | 
						|
        return;
 | 
						|
    case Forward:
 | 
						|
        showNext();
 | 
						|
        break;
 | 
						|
    case Backward:
 | 
						|
        showPrevious();
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::keyPressEvent(QKeyEvent *event)
 | 
						|
{
 | 
						|
	if((event->key() == Qt::Key_Left && !flowRightToLeft) || (event->key() == Qt::Key_Right && flowRightToLeft))
 | 
						|
	{
 | 
						|
		if(event->modifiers() == Qt::ControlModifier)
 | 
						|
			setCurrentIndex((currentSelected-10<0)?0:currentSelected-10);
 | 
						|
		else
 | 
						|
			showPrevious();
 | 
						|
		event->accept();
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if((event->key() == Qt::Key_Right && !flowRightToLeft) || (event->key() == Qt::Key_Left && flowRightToLeft))
 | 
						|
	{
 | 
						|
		if(event->modifiers() == Qt::ControlModifier)
 | 
						|
			setCurrentIndex((currentSelected+10>=numObjects)?numObjects-1:currentSelected+10);
 | 
						|
		else
 | 
						|
			showNext();
 | 
						|
		event->accept();
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	if(event->key() == Qt::Key_Up)
 | 
						|
	{
 | 
						|
    //emit selected(centerIndex());
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	event->ignore();
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::mousePressEvent(QMouseEvent *event)
 | 
						|
{
 | 
						|
	if(event->button() == Qt::LeftButton)
 | 
						|
	{
 | 
						|
		float x,y;
 | 
						|
        float pixelRatio = devicePixelRatio();
 | 
						|
        x = event->x()*pixelRatio;
 | 
						|
        y = event->y()*pixelRatio;
 | 
						|
		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 && !flowRightToLeft) || (posX <=-0.5 && flowRightToLeft))
 | 
						|
		{
 | 
						|
			//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 && !flowRightToLeft) || (posX >= 0.5 && flowRightToLeft) )
 | 
						|
			showPrevious();
 | 
						|
	} else
 | 
						|
		QGLWidget::mousePressEvent(event);
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderFlowGL::mouseDoubleClickEvent(QMouseEvent* event)
 | 
						|
{
 | 
						|
		float x,y;
 | 
						|
        float pixelRatio = devicePixelRatio();
 | 
						|
        x = event->x()*pixelRatio;
 | 
						|
        y = event->y()*pixelRatio;
 | 
						|
		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 && posX >= -0.5)
 | 
						|
		{
 | 
						|
			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 || hasBeenInitialized)
 | 
						|
		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());
 | 
						|
            QString s = "cover";
 | 
						|
            replace(s.toLocal8Bit().data(), 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;
 | 
						|
			}
 | 
						|
	}
 | 
						|
    delete[] indexes;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderComicFlowGL::remove(int item)
 | 
						|
{
 | 
						|
    worker->lock();
 | 
						|
    worker->reset();
 | 
						|
    YACReaderFlowGL::remove(item);
 | 
						|
    if(item >= 0 && item < paths.size())
 | 
						|
        paths.removeAt(item);
 | 
						|
    worker->unlock();
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderComicFlowGL::resortCovers(QList<int> newOrder)
 | 
						|
{
 | 
						|
    worker->lock();
 | 
						|
    worker->reset();//is this necesary?
 | 
						|
    startAnimationTimer();
 | 
						|
    QList<QString> pathsNew;
 | 
						|
    QVector<bool> loadedNew;
 | 
						|
    QVector<YACReaderComicReadStatus> marksNew;
 | 
						|
    QVector<YACReader3DImage> imagesNew;
 | 
						|
 | 
						|
    int index = 0;
 | 
						|
    foreach (int i, newOrder) {
 | 
						|
        pathsNew << paths.at(i);
 | 
						|
        loadedNew << loaded.at(i);
 | 
						|
        marksNew << marks.at(i);
 | 
						|
        imagesNew << images.at(i);
 | 
						|
        imagesNew.last().index = index++;
 | 
						|
    }
 | 
						|
 | 
						|
    paths = pathsNew;
 | 
						|
    loaded = loadedNew;
 | 
						|
    marks = marksNew;
 | 
						|
    images = imagesNew;
 | 
						|
 | 
						|
    worker->unlock();
 | 
						|
}
 | 
						|
 | 
						|
YACReaderPageFlowGL::YACReaderPageFlowGL(QWidget *parent,struct Preset p )
 | 
						|
	:YACReaderFlowGL(parent,p)
 | 
						|
{
 | 
						|
	worker = new ImageLoaderByteArrayGL(this);
 | 
						|
	worker->flow = this;
 | 
						|
}
 | 
						|
 | 
						|
YACReaderPageFlowGL::~YACReaderPageFlowGL()
 | 
						|
{
 | 
						|
	this->killTimer(timerId);
 | 
						|
	//worker->deleteLater();
 | 
						|
	rawImages.clear();
 | 
						|
}
 | 
						|
 | 
						|
//////////////////////////////////////////////////////////////////////////
 | 
						|
//////////////////////////////////////////////////////////////////////////
 | 
						|
//////////////////////////////////////////////////////////////////////////
 | 
						|
//////////////////////////////////////////////////////////////////////////
 | 
						|
//////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
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());
 | 
						|
            QString s = "cover";
 | 
						|
            replace(s.toLocal8Bit().data(), cover, x, y,idx);
 | 
						|
			loaded[idx] = true;
 | 
						|
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// 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())
 | 
						|
			{
 | 
						|
				worker->generate(i, rawImages.at(i));
 | 
						|
 | 
						|
				delete[] indexes;
 | 
						|
				return;
 | 
						|
			}
 | 
						|
	}
 | 
						|
    delete[] indexes;
 | 
						|
}
 | 
						|
 | 
						|
void YACReaderPageFlowGL::populate(int n)
 | 
						|
{
 | 
						|
	worker->reset();
 | 
						|
	if(lazyPopulateObjects!=-1 || hasBeenInitialized)
 | 
						|
		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;
 | 
						|
	case ultraHigh:
 | 
						|
		 break; //no scaling in ultraHigh
 | 
						|
	}
 | 
						|
 | 
						|
	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::lock()
 | 
						|
{
 | 
						|
	mutex.lock();
 | 
						|
}
 | 
						|
 | 
						|
void ImageLoaderGL::unlock()
 | 
						|
{
 | 
						|
	mutex.unlock();
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 |