git-svn-id: svn://db.shs.com.ru/libs@631 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
271
qglengine/mouse_controller.cpp
Normal file
271
qglengine/mouse_controller.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
MouseController
|
||||
Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include "mouse_controller.h"
|
||||
#include "glmesh.h"
|
||||
#include "qglview.h"
|
||||
#include <qad_types.h>
|
||||
#include <QApplication>
|
||||
#include <QKeyEvent>
|
||||
|
||||
using namespace QGLEngineShaders;
|
||||
|
||||
|
||||
MouseController::MouseController(QGLView * view_): view(view_) {
|
||||
app_scale = 1;
|
||||
lastPos = QPoint(-1, -1);
|
||||
cur_action = RendererService::haNoAction;
|
||||
sel_button = Qt::LeftButton;
|
||||
sel_mod = Qt::ControlModifier;
|
||||
mouse_first = mouseSelect_ = mouseRotate_ = cameraOrbit_ = canSelect_ = true;
|
||||
grabMouse_ = mouse_sec = selecting_ = customMouseMove_ = false;
|
||||
}
|
||||
|
||||
|
||||
MouseController::~MouseController() {
|
||||
}
|
||||
|
||||
|
||||
void MouseController::resize() {
|
||||
mouse_first = true;
|
||||
app_scale = appScale();
|
||||
}
|
||||
|
||||
|
||||
void MouseController::mouseReleaseEvent(QMouseEvent * e) {
|
||||
if (cur_action != RendererService::haNoAction) {
|
||||
mouseMoveEvent(e);
|
||||
return;
|
||||
}
|
||||
bool add_ts = e->modifiers().testFlag(sel_mod);
|
||||
if (selecting_) {
|
||||
selecting_ = false;
|
||||
canSelect_ = true;
|
||||
view->renderer_.mouse_rect = QRect();
|
||||
view->scene_->selectObjects(hov_objects.toList(), add_ts);
|
||||
return;
|
||||
}
|
||||
if (canSelect_ && mouseSelect_ && e->button() == Qt::LeftButton) {
|
||||
if ((lastPos - downPos).manhattanLength() < QApplication::startDragDistance() && !hov_objects.isEmpty()) {
|
||||
view->scene_->selectObject(hov_objects[0], add_ts);
|
||||
}
|
||||
}
|
||||
canSelect_ = e->buttons() == 0;
|
||||
emit view->glMouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void MouseController::mousePressEvent(QMouseEvent * e) {
|
||||
downPos = e->pos();
|
||||
if (cur_action != RendererService::haNoAction && e->buttons() == Qt::LeftButton) {
|
||||
return;
|
||||
}
|
||||
if (selecting_) {
|
||||
selecting_ = false;
|
||||
view->renderer_.mouse_rect = QRect();
|
||||
return;
|
||||
}
|
||||
if (!QRect(QPoint(), view->size()).contains(e->pos())) return;
|
||||
lastPos = e->pos();
|
||||
downPos = lastPos;
|
||||
emit view->glMousePressEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void MouseController::mouseMoveEvent(QMouseEvent * e) {
|
||||
QPoint cpos = e->pos();
|
||||
if (cur_action != RendererService::haNoAction && (e->buttons() == Qt::LeftButton)) {
|
||||
RendererService & rs(view->renderer_.rend_service);
|
||||
QList<ObjectBase*> objects = view->scene_->selectedObjects(true);
|
||||
QVector<int> axis;
|
||||
switch (cur_action) {
|
||||
case RendererService::haMove:
|
||||
if (cur_handle.testFlag(RendererService::hmMoveX)) axis << 0;
|
||||
if (cur_handle.testFlag(RendererService::hmMoveY)) axis << 1;
|
||||
if (cur_handle.testFlag(RendererService::hmMoveZ)) axis << 2;
|
||||
break;
|
||||
case RendererService::haRotate:
|
||||
if (cur_handle.testFlag(RendererService::hmRotateX)) axis << 0;
|
||||
if (cur_handle.testFlag(RendererService::hmRotateY)) axis << 1;
|
||||
if (cur_handle.testFlag(RendererService::hmRotateZ)) axis << 2;
|
||||
break;
|
||||
case RendererService::haScale:
|
||||
if (cur_handle.testFlag(RendererService::hmScaleX)) axis << 0;
|
||||
if (cur_handle.testFlag(RendererService::hmScaleY)) axis << 1;
|
||||
if (cur_handle.testFlag(RendererService::hmScaleZ)) axis << 2;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
QVector<QVector3D> scales;
|
||||
foreach (int a, axis) {
|
||||
QVector3D axe_vector; axe_vector[a] = 1.;
|
||||
QMatrix4x4 axis_mat = view->camera()->fullViewMatrix() * rs.axis_mat;
|
||||
QVector3D center_screen = axis_mat * rs.selection_center;
|
||||
QVector3D axe_screen = ((axis_mat * (rs.selection_center + axe_vector)) - center_screen).normalized();
|
||||
QVector3D mouse_vector(cpos - lastPos);
|
||||
mouse_vector[1] *= -1.;
|
||||
if (cur_action == RendererService::haMove) {
|
||||
double len_scl = 1. / QVector3D(axe_screen.x(), axe_screen.y(), 1.E-6).length();
|
||||
mouse_vector /= QVector3D(view->width(), view->height(), 1);
|
||||
mouse_vector *= -center_screen.z() * len_scl;
|
||||
axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector);
|
||||
QMatrix4x4 pmat;
|
||||
foreach (ObjectBase * o, objects) {
|
||||
pmat.setToIdentity();
|
||||
if (o->parent()) {
|
||||
pmat = o->parent()->worldTransform();
|
||||
pmat.setColumn(3, QVector4D(0,0,0,1));
|
||||
double det = pmat.determinant();
|
||||
if (det > 0.) pmat /= sqrt(det);
|
||||
}
|
||||
o->move((QVector4D(axe_vector, 0) * pmat).toVector3D());
|
||||
}
|
||||
}
|
||||
if (cur_action == RendererService::haRotate) {
|
||||
axe_screen.setZ(0.);
|
||||
axe_screen.normalize();
|
||||
QVector3D norm = QVector3D(axe_screen.y(), -axe_screen.x(), 0.);
|
||||
axe_vector *= QVector3D::dotProduct(mouse_vector, norm) / 2. / app_scale;
|
||||
foreach (ObjectBase * o, objects)
|
||||
o->setRotation(o->rotation() + axe_vector);
|
||||
}
|
||||
if (cur_action == RendererService::haScale) {
|
||||
mouse_vector /= QVector3D(view->width(), view->height(), 1);
|
||||
mouse_vector *= 3. / app_scale;
|
||||
axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector);
|
||||
scales << axe_vector;
|
||||
}
|
||||
}
|
||||
//if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ ) cs = Qt::SplitHCursor;
|
||||
if (cur_action == RendererService::haScale) {
|
||||
double sc = 0., max = 0.;
|
||||
foreach (const QVector3D & s, scales) {
|
||||
double v = QVector3D::dotProduct(s, QVector3D(1,1,1));
|
||||
sc += v;
|
||||
max = qMax(max, qAbs(v));
|
||||
}
|
||||
sc = max * (sc > 0. ? 1. : -1);
|
||||
QVector3D axe_vector;
|
||||
foreach (int a, axis)
|
||||
axe_vector[a] = 1.;
|
||||
foreach (ObjectBase * o, objects)
|
||||
o->scale(QVector3D(1,1,1) + (axe_vector * sc));
|
||||
QCursor::setPos(view->mapToGlobal(downPos));
|
||||
} else
|
||||
lastPos = e->pos();
|
||||
return;
|
||||
}
|
||||
if (selecting_) {
|
||||
view->renderer_.mouse_rect = QRect(downPos, cpos).normalized();
|
||||
return;
|
||||
}
|
||||
if (e->buttons().testFlag(Qt::LeftButton)) {
|
||||
if ((cpos - downPos).manhattanLength() >= QApplication::startDragDistance()) {
|
||||
selecting_ = true;
|
||||
canSelect_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
QRect g_rect(QPoint(), view->size());
|
||||
if (mouseRotate_) {
|
||||
float dx = e->x() - lastPos.x();
|
||||
float dy = e->y() - lastPos.y();
|
||||
if (e->buttons().testFlag(Qt::MidButton)) {
|
||||
if (cameraOrbit_) {
|
||||
view->camera()->orbitZ(dx / 4.f);
|
||||
view->camera()->orbitXY(dy / 4.f);
|
||||
} else {
|
||||
view->camera()->rotateZ(dx / 4.f);
|
||||
view->camera()->rotateXY(dy / 4.f);
|
||||
}
|
||||
emit view->cameraPosChanged(view->camera()->pos());
|
||||
} else if (e->buttons().testFlag(Qt::RightButton)) {
|
||||
float ad = view->camera()->distance();
|
||||
view->camera()->moveLeft(dx / 1000.f * ad);
|
||||
view->camera()->moveUp(dy / 1000.f * ad);
|
||||
emit view->cameraPosChanged(view->camera()->pos());
|
||||
}
|
||||
}
|
||||
lastPos = e->pos();
|
||||
if (customMouseMove_) emit view->customMouseMoveEvent(e->pos(), lastPos, e->buttons());
|
||||
if (e->buttons() == 0) {
|
||||
cur_handle = 0;
|
||||
cur_action = RendererService::haNoAction;
|
||||
Qt::CursorShape cs = Qt::CrossCursor;
|
||||
if (view->renderer_.edit_mode) {
|
||||
uint hid = view->renderer_.rend_selection.id_hover;
|
||||
cur_handle = (RendererService::HandleMesh)hid;
|
||||
if (hid >= RendererService::hmMoveX && hid <= RendererService::hmMaxMove ) {
|
||||
cur_action = RendererService::haMove;
|
||||
cs = Qt::SizeAllCursor;
|
||||
}
|
||||
if (hid >= RendererService::hmRotateX && hid <= RendererService::hmMaxRotate) {
|
||||
cur_action = RendererService::haRotate;
|
||||
cs = Qt::PointingHandCursor;
|
||||
}
|
||||
if (hid >= RendererService::hmScaleX && hid <= RendererService::hmMaxScale ) {
|
||||
cur_action = RendererService::haScale;
|
||||
cs = Qt::SplitHCursor;
|
||||
}
|
||||
}
|
||||
if (cur_action == RendererService::haNoAction)
|
||||
cur_handle = 0;
|
||||
view->setCursor(cs);
|
||||
view->renderer_.rend_service.current_handle = cur_handle;
|
||||
}
|
||||
if (grabMouse_) {
|
||||
QCursor::setPos(view->mapToGlobal(QRect(QPoint(), view->size()).center()));
|
||||
if (mouse_sec) {
|
||||
mouse_sec = false;
|
||||
return;
|
||||
}
|
||||
if (mouse_first) {
|
||||
mouse_first = false;
|
||||
mouse_sec = true;
|
||||
return;
|
||||
}
|
||||
lastPos = g_rect.center();
|
||||
int dx = e->x() - lastPos.x();
|
||||
int dy = e->y() - lastPos.y();
|
||||
emit view->glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers()));
|
||||
return;
|
||||
}
|
||||
emit view->glMouseMoveEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void MouseController::wheelEvent(QWheelEvent * e) {
|
||||
if (mouseRotate_) {
|
||||
if (e->delta() > 0) view->camera()->flyCloser(0.1f);
|
||||
if (e->delta() < 0) view->camera()->flyFarer(0.1f);
|
||||
emit view->cameraPosChanged(view->camera()->pos());
|
||||
}
|
||||
emit view->glWheelEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void MouseController::leaveEvent(QEvent * ) {
|
||||
lastPos = QPoint(-1, -1);
|
||||
//qDebug() << lastPos;
|
||||
}
|
||||
|
||||
|
||||
void MouseController::mouseDoubleClickEvent(QMouseEvent * e) {
|
||||
if (e->buttons().testFlag(Qt::MidButton))
|
||||
emit view->doubleClick();
|
||||
}
|
||||
Reference in New Issue
Block a user