src/glRenderer.h

Wed, 16 Jul 2014 15:00:41 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Wed, 16 Jul 2014 15:00:41 +0300
changeset 844
11587d419d2f
parent 830
a741a0b9df49
child 855
e16f1587ef44
permissions
-rw-r--r--

- changed copyright lines to use my legal name instead of my nickname

/*
 *  LDForge: LDraw parts authoring CAD
 *  Copyright (C) 2013, 2014 Teemu Piippo
 *
 *  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 3 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, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#include <QGLWidget>
#include "main.h"
#include "macros.h"
#include "ldObject.h"
#include "ldDocument.h"
#include "glShared.h"
#include "editmodes/abstractEditMode.h"

class GLCompiler;
class MessageManager;
class QDialogButtonBox;
class RadioGroup;
class QDoubleSpinBox;
class QSpinBox;
class QLineEdit;
class QTimer;
class MagicWandMode;

//
// Meta for overlays
//
struct LDGLOverlay
{
	Vertex			v0,
					v1;
	int				ox,
					oy;
	double			lw,
					lh;
	QString			fname;
	QImage*			img;
	bool			invalid;
};

struct LDFixedCamera
{
	const char		glrotate[3];
	const Axis		axisX,
					axisY;
	const bool		negX,
					negY,
					negatedDepth; // is greater depth value closer to camera?
};

//
// Document-specific data
//
struct LDGLData
{
	double			rotX,
					rotY,
					rotZ,
					panX[7],
					panY[7],
					zoom[7];
	double			depthValues[6];
	LDGLOverlay		overlays[6];
	bool			init;
	bool			needZoomToFit;

	LDGLData() :
		rotX (0.0),
		rotY (0.0),
		rotZ (0.0),
		init (false),
		needZoomToFit (true)
	{
		for (int i = 0; i < 7; ++i)
		{
			if (i < 6)
			{
				overlays[i].img = null;
				overlays[i].invalid = false;
				depthValues[i] = 0.0f;
			}

			zoom[i] = 30.0;
			panX[i] = 0.0;
			panY[i] = 0.0;
		}
	}
};

enum ECamera
{
	ETopCamera,
	EFrontCamera,
	ELeftCamera,
	EBottomCamera,
	EBackCamera,
	ERightCamera,
	EFreeCamera,

	ENumCameras,
	EFirstCamera = ETopCamera
};

NUMERIC_ENUM_OPERATORS (ECamera)

//
// CameraIcon::img is a heap-allocated QPixmap because otherwise it gets
// initialized before program gets to main() and constructs a QApplication
// and Qt doesn't like that.
//
struct CameraIcon
{
	QPixmap*		img;
	QRect			srcRect,
					destRect,
					selRect;
	ECamera			cam;
};

//
// The main renderer object, draws the brick on the screen, manages the camera
// and selection picking. The instance of GLRenderer is accessible as
// g_win->R()
//
class GLRenderer : public QGLWidget
{
public:
	Q_OBJECT
	PROPERTY (public,	bool,				isDrawOnly,		setDrawOnly,		STOCK_WRITE)
	PROPERTY (public,	MessageManager*,	messageLog, 	setMessageLog,		STOCK_WRITE)
	PROPERTY (private,	bool,				isPicking,		setPicking,			CUSTOM_WRITE)
	PROPERTY (public,	LDDocumentPtr,		document,		setDocument,		CUSTOM_WRITE)
	PROPERTY (private,	GLCompiler*,		compiler,		setCompiler,		STOCK_WRITE)
	PROPERTY (public,	LDObjectWeakPtr,	objectAtCursor,	setObjectAtCursor,	STOCK_WRITE)
	PROPERTY (private,	bool,				isCameraMoving,	setCameraMoving,	STOCK_WRITE)

public:
	GLRenderer (QWidget* parent = null);
	~GLRenderer();

	inline ECamera			camera() const;
	void					clearOverlay();
	void					compileObject (LDObjectPtr obj);
	Vertex					coordconv2_3 (const QPoint& pos2d, bool snap) const;
	QPoint					coordconv3_2 (const Vertex& pos3d) const;
	EditModeType			currentEditModeType() const;
	void					drawBlip (QPainter& paint, QPoint pos) const;
	void					drawGLScene();
	void					forgetObject (LDObjectPtr obj);
	Axis					getCameraAxis (bool y, ECamera camid = (ECamera) -1);
	const char*				getCameraName() const;
	double					getDepthValue() const;
	LDFixedCamera const&	getFixedCamera (ECamera cam) const;
	void					getRelativeAxes (Axis& relX, Axis& relY) const;
	Axis					getRelativeZ() const;
	LDGLOverlay&			getOverlay (int newcam);
	uchar*					getScreencap (int& w, int& h);
	void					hardRefresh();
	void					highlightCursorObject();
	void					initGLData();
	void					initOverlaysFromObjects();
	QPen					linePen() const;
	bool					mouseHasMoved() const;
	QPoint const&			mousePosition() const;
	void					needZoomToFit();
	void					pick (int mouseX, int mouseY, bool additive);
	void					pick (QRect const& range, bool additive);
	LDObjectPtr				pickOneObject (int mouseX, int mouseY);
	Vertex const&			position3D() const;
	void					refresh();
	void					resetAngles();
	void					resetAllAngles();
	void					setBackground();
	void					setCamera (const ECamera cam);
	void					setDepthValue (double depth);
	void					setEditMode (EditModeType type);
	bool					setupOverlay (ECamera cam, QString file, int x, int y, int w, int h);
	QPen					textPen() const;
	void					updateOverlayObjects();
	void					zoomNotch (bool inward);

	static QColor			getMainColor();

protected:
	void					contextMenuEvent (QContextMenuEvent* ev);
	void					dragEnterEvent (QDragEnterEvent* ev);
	void					dropEvent (QDropEvent* ev);
	void					initializeGL();
	void					keyPressEvent (QKeyEvent* ev);
	void					keyReleaseEvent (QKeyEvent* ev);
	void					leaveEvent (QEvent* ev);
	void					mouseDoubleClickEvent (QMouseEvent* ev);
	void					mousePressEvent (QMouseEvent* ev);
	void					mouseMoveEvent (QMouseEvent* ev);
	void					mouseReleaseEvent (QMouseEvent* ev);
	void					paintEvent (QPaintEvent* ev);
	void					resizeGL (int w, int h);
	void					wheelEvent (QWheelEvent* ev);

private:
	CameraIcon				m_cameraIcons[7];
	QTimer*					m_toolTipTimer;
	Qt::MouseButtons		m_lastButtons;
	Qt::KeyboardModifiers	m_keymods;
	Vertex					m_position3D;
	double					m_virtWidth,
							m_virtHeight;
	bool					m_darkbg,
							m_drawToolTip,
							m_screencap,
							m_panning;
	QPoint					m_mousePosition,
							m_globalpos;
	QPen					m_thinBorderPen;
	ECamera					m_camera,
							m_toolTipCamera;
	GLuint					m_axeslist;
	int						m_width,
							m_height,
							m_totalmove;
	QColor					m_bgcolor;
	AbstractEditMode*		m_editmode;

	void					calcCameraIcons();
	void					clampAngle (double& angle) const;
	inline LDGLData&		currentDocumentData() const;
	void					drawVBOs (EVBOSurface surface, EVBOComplement colors, GLenum type);
	LDOverlayPtr			findOverlayObject (ECamera cam);
	inline double&			pan (Axis ax);
	inline const double&	pan (Axis ax) const;
	inline double&			rot (Axis ax);
	inline double&			zoom();
	void					zoomToFit();
	void					zoomAllToFit();

	template<typename... Args>
	inline QString format (QString fmtstr, Args... args)
	{
		return ::format (fmtstr, args...);
	}

private slots:
	void	slot_toolTipTimer();
	void	initializeAxes();
};

inline ECamera GLRenderer::camera() const
{
	return m_camera;
}

inline LDGLData& GLRenderer::currentDocumentData() const
{
	return *document()->getGLData();
}

inline double& GLRenderer::rot (Axis ax)
{
	return
		(ax == X) ? currentDocumentData().rotX :
		(ax == Y) ? currentDocumentData().rotY :
					currentDocumentData().rotZ;
}

inline double& GLRenderer::pan (Axis ax)
{
	return (ax == X) ? currentDocumentData().panX[camera()] :
		currentDocumentData().panY[camera()];
}

inline double const& GLRenderer::pan (Axis ax) const
{
	return (ax == X) ? currentDocumentData().panX[camera()] :
		currentDocumentData().panY[camera()];
}

inline double& GLRenderer::zoom()
{
	return currentDocumentData().zoom[camera()];
}

extern const char* g_CameraNames[7];

mercurial