leocad/qt/lc_qglwidget.cpp

405 lines
9.4 KiB
C++
Raw Normal View History

2013-08-09 06:57:18 +02:00
#include "lc_global.h"
#include "lc_qglwidget.h"
#include "lc_glwidget.h"
2015-05-09 21:54:29 +02:00
#include "lc_glextensions.h"
2013-08-09 06:57:18 +02:00
#include "project.h"
#include "lc_library.h"
#include "lc_application.h"
2013-08-16 03:25:51 +02:00
#include "lc_mainwindow.h"
#include "lc_partselectionwidget.h"
2014-04-14 05:20:16 +02:00
#include "lc_context.h"
2014-05-27 00:58:08 +02:00
#include "view.h"
#include "texfont.h"
2018-10-29 01:59:01 +01:00
#include "lc_viewsphere.h"
2018-09-24 04:31:33 +02:00
#include "lc_stringcache.h"
#include "lc_texture.h"
#include "lc_mesh.h"
2016-12-28 22:30:31 +01:00
#include "lc_profile.h"
2016-12-28 22:30:31 +01:00
static QList<QGLWidget*> gWidgetList;
2013-08-09 06:57:18 +02:00
void lcGLWidget::MakeCurrent()
{
QGLWidget* Widget = (QGLWidget*)mWidget;
Widget->makeCurrent();
}
void lcGLWidget::Redraw()
{
2014-09-15 00:41:22 +02:00
lcQGLWidget* Widget = (lcQGLWidget*)mWidget;
2013-08-09 06:57:18 +02:00
2014-09-15 00:41:22 +02:00
Widget->mUpdateTimer.start(0);
2013-08-09 06:57:18 +02:00
}
void lcGLWidget::SetCursor(LC_CURSOR_TYPE CursorType)
{
if (mCursorType == CursorType)
return;
struct lcCursorInfo
{
int x, y;
const char* Name;
};
const lcCursorInfo Cursors[LC_CURSOR_COUNT] =
{
{ 0, 0, "" }, // LC_CURSOR_DEFAULT
{ 8, 3, ":/resources/cursor_insert" }, // LC_CURSOR_BRICK
{ 15, 15, ":/resources/cursor_light" }, // LC_CURSOR_LIGHT
{ 7, 10, ":/resources/cursor_spotlight" }, // LC_CURSOR_SPOTLIGHT
{ 15, 9, ":/resources/cursor_camera" }, // LC_CURSOR_CAMERA
{ 0, 2, ":/resources/cursor_select" }, // LC_CURSOR_SELECT
{ 0, 2, ":/resources/cursor_select_add" }, // LC_CURSOR_SELECT_ADD
{ 0, 2, ":/resources/cursor_select_remove" }, // LC_CURSOR_SELECT_REMOVE
{ 15, 15, ":/resources/cursor_move" }, // LC_CURSOR_MOVE
{ 15, 15, ":/resources/cursor_rotate" }, // LC_CURSOR_ROTATE
{ 15, 15, ":/resources/cursor_rotatex" }, // LC_CURSOR_ROTATEX
{ 15, 15, ":/resources/cursor_rotatey" }, // LC_CURSOR_ROTATEY
{ 0, 10, ":/resources/cursor_delete" }, // LC_CURSOR_DELETE
{ 14, 14, ":/resources/cursor_paint" }, // LC_CURSOR_PAINT
{ 15, 15, ":/resources/cursor_zoom" }, // LC_CURSOR_ZOOM
{ 9, 9, ":/resources/cursor_zoom_region" }, // LC_CURSOR_ZOOM_REGION
{ 15, 15, ":/resources/cursor_pan" }, // LC_CURSOR_PAN
{ 15, 15, ":/resources/cursor_roll" }, // LC_CURSOR_ROLL
{ 15, 15, ":/resources/cursor_rotate_view" }, // LC_CURSOR_ROTATE_VIEW
2013-08-09 06:57:18 +02:00
};
2019-12-09 20:43:54 +01:00
static_assert(LC_ARRAY_COUNT(Cursors) == LC_CURSOR_COUNT, "Array size mismatch");
2013-08-09 06:57:18 +02:00
QGLWidget* widget = (QGLWidget*)mWidget;
if (CursorType != LC_CURSOR_DEFAULT && CursorType < LC_CURSOR_COUNT)
{
const lcCursorInfo& Cursor = Cursors[CursorType];
widget->setCursor(QCursor(QPixmap(Cursor.Name), Cursor.x, Cursor.y));
mCursorType = CursorType;
}
else
{
widget->unsetCursor();
mCursorType = LC_CURSOR_DEFAULT;
}
}
2016-12-28 22:30:31 +01:00
lcQGLWidget::lcQGLWidget(QWidget *parent, lcGLWidget *owner, bool view)
: QGLWidget(parent, gWidgetList.isEmpty() ? nullptr : gWidgetList.first())
2013-08-09 06:57:18 +02:00
{
2015-02-10 23:34:04 +01:00
mWheelAccumulator = 0;
2013-08-09 06:57:18 +02:00
widget = owner;
widget->mWidget = this;
2014-09-15 00:41:22 +02:00
mUpdateTimer.setSingleShot(true);
connect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
2013-08-09 06:57:18 +02:00
widget->MakeCurrent();
// TODO: Find a better place for the grid texture and font
2018-09-24 04:31:33 +02:00
gStringCache.AddRef(widget->mContext);
2017-03-25 20:29:28 +01:00
gTexFont.Load(widget->mContext);
2016-12-28 22:30:31 +01:00
if (gWidgetList.isEmpty())
{
2015-05-09 21:54:29 +02:00
lcInitializeGLExtensions(context());
2015-05-17 01:04:35 +02:00
lcContext::CreateResources();
View::CreateResources(widget->mContext);
lcViewSphere::CreateResources(widget->mContext);
2017-08-25 21:57:14 +02:00
if (!gSupportsShaderObjects && lcGetPreferences().mShadingMode == LC_SHADING_DEFAULT_LIGHTS)
lcGetPreferences().mShadingMode = LC_SHADING_FLAT;
if (!gSupportsFramebufferObjectARB && !gSupportsFramebufferObjectEXT)
gMainWindow->GetPartSelectionWidget()->DisableIconMode();
gPlaceholderMesh = new lcMesh;
gPlaceholderMesh->CreateBox();
}
2016-12-28 22:30:31 +01:00
gWidgetList.append(this);
2015-05-09 21:54:29 +02:00
widget->OnInitialUpdate();
2013-08-09 06:57:18 +02:00
preferredSize = QSize(0, 0);
setMouseTracking(true);
mIsView = view;
if (mIsView)
2013-08-09 06:57:18 +02:00
{
setFocusPolicy(Qt::StrongFocus);
setAcceptDrops(true);
}
}
lcQGLWidget::~lcQGLWidget()
{
2016-12-28 22:30:31 +01:00
gWidgetList.removeOne(this);
2018-09-24 04:31:33 +02:00
gStringCache.Release(widget->mContext);
gTexFont.Release();
2015-05-17 01:04:35 +02:00
makeCurrent();
2016-12-28 22:30:31 +01:00
if (gWidgetList.isEmpty())
{
2016-12-28 22:30:31 +01:00
lcGetPiecesLibrary()->ReleaseBuffers(widget->mContext);
View::DestroyResources(widget->mContext);
2015-05-17 01:04:35 +02:00
lcContext::DestroyResources();
lcViewSphere::DestroyResources(widget->mContext);
delete gPlaceholderMesh;
gPlaceholderMesh = nullptr;
}
2016-03-06 02:47:00 +01:00
delete widget;
2013-08-09 06:57:18 +02:00
}
QSize lcQGLWidget::sizeHint() const
{
if (preferredSize.isEmpty())
return QGLWidget::sizeHint();
else
return preferredSize;
}
void lcQGLWidget::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
2013-08-09 06:57:18 +02:00
}
void lcQGLWidget::resizeGL(int width, int height)
{
widget->mWidth = width;
widget->mHeight = height;
}
void lcQGLWidget::paintGL()
{
widget->OnDraw();
}
void lcQGLWidget::keyPressEvent(QKeyEvent *event)
{
if (mIsView && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Shift))
2013-08-09 06:57:18 +02:00
{
2016-04-23 02:17:33 +02:00
widget->mInputState.Modifiers = event->modifiers();
2013-08-09 06:57:18 +02:00
widget->OnUpdateCursor();
}
QGLWidget::keyPressEvent(event);
}
void lcQGLWidget::keyReleaseEvent(QKeyEvent *event)
{
if (mIsView && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Shift))
2013-08-09 06:57:18 +02:00
{
2016-04-23 02:17:33 +02:00
widget->mInputState.Modifiers = event->modifiers();
2013-08-09 06:57:18 +02:00
widget->OnUpdateCursor();
}
QGLWidget::keyReleaseEvent(event);
}
void lcQGLWidget::mousePressEvent(QMouseEvent *event)
{
2014-04-08 03:04:32 +02:00
float scale = deviceScale();
2014-04-06 23:44:58 +02:00
widget->mInputState.x = event->x() * scale;
widget->mInputState.y = widget->mHeight - event->y() * scale - 1;
2016-04-23 02:17:33 +02:00
widget->mInputState.Modifiers = event->modifiers();
2013-08-09 06:57:18 +02:00
switch (event->button())
{
case Qt::LeftButton:
widget->OnLeftButtonDown();
break;
2013-08-09 06:57:18 +02:00
case Qt::MidButton:
widget->OnMiddleButtonDown();
break;
2013-08-09 06:57:18 +02:00
case Qt::RightButton:
widget->OnRightButtonDown();
break;
2015-09-18 07:53:43 +02:00
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
case Qt::BackButton:
widget->OnBackButtonDown();
break;
case Qt::ForwardButton:
widget->OnForwardButtonDown();
break;
2015-09-18 07:53:43 +02:00
#endif
2013-08-09 06:57:18 +02:00
default:
break;
}
}
void lcQGLWidget::mouseReleaseEvent(QMouseEvent *event)
{
2014-04-08 03:04:32 +02:00
float scale = deviceScale();
2014-04-06 23:44:58 +02:00
widget->mInputState.x = event->x() * scale;
widget->mInputState.y = widget->mHeight - event->y() * scale - 1;
2016-04-23 02:17:33 +02:00
widget->mInputState.Modifiers = event->modifiers();
2013-08-09 06:57:18 +02:00
switch (event->button())
{
case Qt::LeftButton:
widget->OnLeftButtonUp();
break;
2013-08-09 06:57:18 +02:00
case Qt::MidButton:
widget->OnMiddleButtonUp();
break;
2013-08-09 06:57:18 +02:00
case Qt::RightButton:
widget->OnRightButtonUp();
break;
2015-09-18 07:53:43 +02:00
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
case Qt::BackButton:
widget->OnBackButtonUp();
break;
case Qt::ForwardButton:
widget->OnForwardButtonUp();
break;
2015-09-18 07:53:43 +02:00
#endif
2013-08-09 06:57:18 +02:00
default:
break;
}
}
2014-04-26 08:23:12 +02:00
void lcQGLWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
float scale = deviceScale();
widget->mInputState.x = event->x() * scale;
widget->mInputState.y = widget->mHeight - event->y() * scale - 1;
2016-04-23 02:17:33 +02:00
widget->mInputState.Modifiers = event->modifiers();
2014-04-26 08:23:12 +02:00
switch (event->button())
{
case Qt::LeftButton:
widget->OnLeftButtonDoubleClick();
break;
default:
break;
}
}
2013-08-09 06:57:18 +02:00
void lcQGLWidget::mouseMoveEvent(QMouseEvent *event)
{
2014-04-08 03:04:32 +02:00
float scale = deviceScale();
2014-04-06 23:44:58 +02:00
widget->mInputState.x = event->x() * scale;
widget->mInputState.y = widget->mHeight - event->y() * scale - 1;
2016-04-23 02:17:33 +02:00
widget->mInputState.Modifiers = event->modifiers();
2013-08-09 06:57:18 +02:00
widget->OnMouseMove();
}
void lcQGLWidget::wheelEvent(QWheelEvent *event)
{
2015-02-10 23:34:04 +01:00
if ((event->orientation() & Qt::Vertical) == 0)
{
event->ignore();
return;
}
2014-04-08 03:04:32 +02:00
float scale = deviceScale();
2014-04-06 23:44:58 +02:00
widget->mInputState.x = event->x() * scale;
widget->mInputState.y = widget->mHeight - event->y() * scale - 1;
2016-04-23 02:17:33 +02:00
widget->mInputState.Modifiers = event->modifiers();
2013-08-09 06:57:18 +02:00
2015-02-07 04:08:18 +01:00
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
2015-02-10 23:34:04 +01:00
mWheelAccumulator += event->angleDelta().y() / 8;
2015-02-07 04:08:18 +01:00
#else
2015-02-10 23:34:04 +01:00
mWheelAccumulator += event->delta() / 8;
2015-02-07 04:08:18 +01:00
#endif
2015-02-10 23:34:04 +01:00
int numSteps = mWheelAccumulator / 15;
2013-08-09 06:57:18 +02:00
2015-02-10 23:34:04 +01:00
if (numSteps)
{
widget->OnMouseWheel(numSteps);
mWheelAccumulator -= numSteps * 15;
}
2013-08-09 06:57:18 +02:00
event->accept();
}
void lcQGLWidget::dragEnterEvent(QDragEnterEvent* DragEnterEvent)
2013-08-09 06:57:18 +02:00
{
if (mIsView)
2013-08-09 06:57:18 +02:00
{
const QMimeData* MimeData = DragEnterEvent->mimeData();
if (MimeData->hasFormat("application/vnd.leocad-part"))
{
DragEnterEvent->acceptProposedAction();
((View*)widget)->BeginDrag(lcDragState::PIECE);
}
else if (MimeData->hasFormat("application/vnd.leocad-color"))
{
DragEnterEvent->acceptProposedAction();
((View*)widget)->BeginDrag(lcDragState::COLOR);
}
2013-08-09 06:57:18 +02:00
}
else
DragEnterEvent->ignore();
2013-08-09 06:57:18 +02:00
}
void lcQGLWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
if (!mIsView)
2013-08-09 06:57:18 +02:00
return;
((View*)widget)->EndDrag(false);
2013-08-09 06:57:18 +02:00
event->accept();
}
void lcQGLWidget::dragMoveEvent(QDragMoveEvent* DragMoveEvent)
2013-08-09 06:57:18 +02:00
{
if (mIsView)
{
const QMimeData* MimeData = DragMoveEvent->mimeData();
2013-08-09 06:57:18 +02:00
if (MimeData->hasFormat("application/vnd.leocad-part") || MimeData->hasFormat("application/vnd.leocad-color"))
{
float scale = deviceScale();
2014-04-08 03:04:32 +02:00
widget->mInputState.x = DragMoveEvent->pos().x() * scale;
widget->mInputState.y = widget->mHeight - DragMoveEvent->pos().y() * scale - 1;
widget->mInputState.Modifiers = DragMoveEvent->keyboardModifiers();
2014-05-27 00:58:08 +02:00
widget->OnMouseMove();
2013-08-09 06:57:18 +02:00
DragMoveEvent->accept();
return;
}
}
QGLWidget::dragMoveEvent(DragMoveEvent);
2013-08-09 06:57:18 +02:00
}
void lcQGLWidget::dropEvent(QDropEvent* DropEvent)
2013-08-09 06:57:18 +02:00
{
if (mIsView)
{
const QMimeData* MimeData = DropEvent->mimeData();
2013-08-09 06:57:18 +02:00
if (MimeData->hasFormat("application/vnd.leocad-part") || MimeData->hasFormat("application/vnd.leocad-color"))
{
((View*)widget)->EndDrag(true);
setFocus(Qt::MouseFocusReason);
2013-08-09 06:57:18 +02:00
DropEvent->accept();
return;
}
}
QGLWidget::dropEvent(DropEvent);
2013-08-09 06:57:18 +02:00
}