summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2016-06-15 15:47:03 +0300
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2016-06-16 06:37:53 +0000
commited460dcff9d9fa3440cfdc3226b1458f49716555 (patch)
tree4cc883fd181f6e6428c87722c937d379278fad04
parentdab94ca0ce52a3c3ccc8cf4c3ccfe3a0be80f0c6 (diff)
Changed snap to grid to snap corners to the grid.
Mouse modifier keys ctrl and alt can now also be stacked on translate and scale. Change-Id: I5252b9d98482e7ea9ff7244e1a51239d68dbdf31 Reviewed-by: Titta Heikkala <titta.heikkala@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--editorlib/qml/main.qml8
-rw-r--r--editorlib/src/editorscene.cpp200
-rw-r--r--editorlib/src/editorscene.h13
3 files changed, 151 insertions, 70 deletions
diff --git a/editorlib/qml/main.qml b/editorlib/qml/main.qml
index 3f9c84c..c818bdb 100644
--- a/editorlib/qml/main.qml
+++ b/editorlib/qml/main.qml
@@ -557,6 +557,14 @@ ApplicationWindow {
handleType: EditorScene.DragScale
handleIndex: 7
}
+
+ // Debug handle for visualizing world positions, uncomment to use.
+ // You can show debug handles with EditorScene::showDebugHandle().
+// DragHandle {
+// handleType: EditorScene.DragDebug
+// color: "green"
+// baseZ: 4
+// }
}
}
}
diff --git a/editorlib/src/editorscene.cpp b/editorlib/src/editorscene.cpp
index 789bb75..e0b9570 100644
--- a/editorlib/src/editorscene.cpp
+++ b/editorlib/src/editorscene.cpp
@@ -518,19 +518,41 @@ void EditorScene::dragHandlePress(EditorScene::DragMode dragMode, const QPoint &
if (selectedItem) {
m_dragHandleIndex = handleIndex;
if (dragMode == DragTranslate && m_dragHandleTranslateTransform->isEnabled()) {
- m_cameraViewCenterSelected = false;
Qt3DRender::QCamera *cameraEntity =
qobject_cast<Qt3DRender::QCamera *>(m_selectedEntity);
if (cameraEntity) {
- m_dragInitialTranslationValue = cameraEntity->position();
+ if (m_cameraViewCenterSelected && !m_viewCenterLocked)
+ m_dragInitialWorldTranslationValue = cameraEntity->viewCenter();
+ else
+ m_dragInitialWorldTranslationValue = cameraEntity->position();
} else {
if (handleIndex) {
- m_dragInitialTranslationValue = m_dragHandlesTransform->translation();
+ m_dragInitialWorldTranslationValue = m_dragHandlesTransform->translation();
} else {
- m_dragInitialTranslationValue = m_dragHandlesTransform->matrix()
+ m_dragInitialWorldTranslationValue = m_dragHandlesTransform->matrix()
* m_dragHandleTranslateTransform->matrix() * QVector3D();
}
}
+ m_dragInitialEntityTranslationValue = m_selectedEntityTransform->translation();
+
+ // Calculate snap point offset in world coordinates
+ for (int i = 0; i < dragCornerHandleCount; ++i) {
+ if (cameraEntity) {
+ m_dragEntitySnapOffsets[i] = QVector3D();
+ } else {
+ QVector3D centerHandleAdj = handleIndex
+ ? selectedItem->entityMeshCenter()
+ * m_selectedEntityTransform->scale3D()
+ / selectedItem->selectionTransform()->scale3D()
+ : QVector3D();
+ QVector3D snapPos = (selectedItem->selectionTransform()->matrix()
+ * (m_dragHandleCornerAdjustments.at(i)
+ * QVector3D(0.5f, 0.5f, 0.5f) + centerHandleAdj));
+ snapPos -= selectedItem->selectionBoxCenter();
+ m_dragEntitySnapOffsets[i] = snapPos;
+ }
+ }
+
m_dragEntity = m_selectedEntity;
m_dragMode = DragTranslate;
} else if (dragMode == DragRotate && m_dragHandleRotateTransform->isEnabled()) {
@@ -552,7 +574,7 @@ void EditorScene::dragHandlePress(EditorScene::DragMode dragMode, const QPoint &
}
m_dragEntity = m_selectedEntity;
m_dragMode = DragRotate;
- m_dragInitialRotationValue = selectedItem->entityTransform()->rotation();
+ m_dragInitialRotationValue = m_selectedEntityTransform->rotation();
m_dragInitialHandleTranslation = m_dragHandlesTransform->rotation()
* m_dragHandleRotateTransform->translation();
m_dragInitialCenterTranslation = m_dragHandlesTransform->translation();
@@ -560,9 +582,7 @@ void EditorScene::dragHandlePress(EditorScene::DragMode dragMode, const QPoint &
&& m_dragHandleScaleTransforms.at(0)->isEnabled()) {
m_dragMode = DragScale;
m_dragEntity = m_selectedEntity;
- Qt3DCore::QTransform *itemTransform = selectedItem->entityTransform();
- m_dragInitialScaleValue = itemTransform->scale3D();
- m_dragInitialTranslationValue = itemTransform->translation();
+ m_dragInitialScaleValue = m_selectedEntityTransform->scale3D();
m_dragInitialCenterTranslation = m_dragHandlesTransform->translation();
m_dragInitialHandleTranslation = m_dragHandlesTransform->rotation()
* m_dragHandleScaleTransforms.at(m_dragHandleIndex)->translation();
@@ -769,6 +789,21 @@ Qt3DRender::QObjectPicker *EditorScene::createObjectPickerForEntity(Qt3DCore::QE
return picker;
}
+// Debug handle is useful for visually debugging calculated world positions
+void EditorScene::showDebugHandle(bool show, int handleIndex, const QVector3D &worldPosition)
+{
+ QVector3D screenPoint;
+ if (show) {
+ Qt3DRender::QCamera *camera = frameGraphCamera();
+ screenPoint = EditorUtils::projectRay(
+ camera->viewMatrix(), camera->projectionMatrix(),
+ m_viewport->width(), m_viewport->height(), worldPosition);
+ }
+
+ emit repositionDragHandle(DragDebug, QPoint(screenPoint.x(), screenPoint.y()),
+ show, handleIndex, 0);
+}
+
int EditorScene::cameraIndexForEntity(Qt3DCore::QEntity *entity)
{
int index = -1;
@@ -837,18 +872,20 @@ void EditorScene::dragTranslateSelectedEntity(const QPoint &newPos, bool shiftDo
QVector3D entityTranslation = m_selectedEntityTransform->translation();
Qt3DRender::QCamera *cameraEntity = qobject_cast<Qt3DRender::QCamera *>(m_selectedEntity);
if (cameraEntity) {
- if (m_cameraViewCenterSelected)
+ if (m_cameraViewCenterSelected && !m_viewCenterLocked)
entityTranslation = cameraEntity->viewCenter();
else
entityTranslation = cameraEntity->position();
}
- QVector3D planeOrigin = m_dragInitialTranslationValue;
+ QVector3D helperNormal = helperPlaneNormal();
+ QVector3D planeOrigin = m_dragInitialWorldTranslationValue;
QVector3D planeNormal;
- if (shiftDown || altDown)
+ const bool useCameraNormal = shiftDown || altDown;
+ if (useCameraNormal)
planeNormal = EditorUtils::cameraNormal(frameGraphCamera());
else
- planeNormal = helperPlaneNormal();
+ planeNormal = helperNormal;
float cosAngle = QVector3D::dotProduct(planeOrigin.normalized(), planeNormal);
float planeOffset = planeOrigin.length() * cosAngle;
@@ -866,7 +903,7 @@ void EditorScene::dragTranslateSelectedEntity(const QPoint &newPos, bool shiftDo
if (cameraEntity) {
componentType = EditorSceneItemComponentsModel::CameraEntity;
- if (m_cameraViewCenterSelected)
+ if (m_cameraViewCenterSelected && !m_viewCenterLocked)
propertyName = QStringLiteral("viewCenter");
else
propertyName = QStringLiteral("position");
@@ -874,34 +911,36 @@ void EditorScene::dragTranslateSelectedEntity(const QPoint &newPos, bool shiftDo
propertyName = QStringLiteral("translation");
}
- // If entity has parents with transfroms, those need to be applied in inverse
- QMatrix4x4 totalTransform = EditorUtils::totalAncestralTransform(m_selectedEntity);
- if (m_dragHandleIndex == 0 && !cameraEntity) {
- intersection = totalTransform.inverted()
- * (intersection + m_dragHandlesTransform->rotation()
- * m_dragHandleTranslateTransform->translation());
- } else {
- intersection = totalTransform.inverted() * intersection;
- }
-
+ QVector3D newPosition = intersection;
if (ctrlDown) {
- m_snapToGridIntersection.setX(qRound(intersection.x() / m_gridSize) * m_gridSize);
- m_snapToGridIntersection.setY(qRound(intersection.y() / m_gridSize) * m_gridSize);
- m_snapToGridIntersection.setZ(qRound(intersection.z() / m_gridSize) * m_gridSize);
- } else if (altDown) {
- QVector3D lockedAxis = intersection * helperPlaneNormal();
- if (!qFuzzyCompare(lockedAxis.x(), 0.0f))
- m_snapToGridIntersection.setX(lockedAxis.x());
- else if (!qFuzzyCompare(lockedAxis.y(), 0.0f))
- m_snapToGridIntersection.setY(lockedAxis.y());
- else if (!qFuzzyCompare(lockedAxis.z(), 0.0f))
- m_snapToGridIntersection.setZ(lockedAxis.z());
+ newPosition = snapPosition(intersection,
+ useCameraNormal || helperNormal.x() < 0.5,
+ useCameraNormal || helperNormal.y() < 0.5,
+ useCameraNormal || helperNormal.z() < 0.5);
+ }
+ if (altDown) {
+ QVector3D snapPos = newPosition;
+ newPosition = m_dragInitialEntityTranslationValue;
+ if (helperNormal.x() > 0.5)
+ newPosition.setX(snapPos.x());
+ else if (helperNormal.y() > 0.5)
+ newPosition.setY(snapPos.y());
+ else if (helperNormal.z() > 0.5)
+ newPosition.setZ(snapPos.z());
} else {
- m_snapToGridIntersection = intersection;
+ // If entity has parents with transfroms, those need to be applied in inverse
+ QMatrix4x4 totalTransform = EditorUtils::totalAncestralTransform(m_selectedEntity);
+ if (m_dragHandleIndex == 0 && !cameraEntity) {
+ newPosition = totalTransform.inverted()
+ * (newPosition + m_dragHandlesTransform->rotation()
+ * m_dragHandleTranslateTransform->translation());
+ } else {
+ newPosition = totalTransform.inverted() * newPosition;
+ }
}
m_undoHandler->createChangePropertyCommand(m_selectedEntity->objectName(), componentType,
- propertyName, m_snapToGridIntersection,
+ propertyName, newPosition,
entityTranslation, true);
}
}
@@ -949,23 +988,23 @@ void EditorScene::dragScaleSelectedEntity(const QPoint &newPos, bool shiftDown,
newScale.setX(qMax(qRound(newScale.x()), 1));
newScale.setY(qMax(qRound(newScale.y()), 1));
newScale.setZ(qMax(qRound(newScale.z()), 1));
- m_lockToAxisScale = newScale;
- } else if (altDown) {
- QVector3D lockedAxis = newScale * helperPlaneNormal();
- if (!qFuzzyCompare(lockedAxis.x(), 0.0f))
- m_lockToAxisScale.setX(lockedAxis.x());
- else if (!qFuzzyCompare(lockedAxis.y(), 0.0f))
- m_lockToAxisScale.setY(lockedAxis.y());
- else if (!qFuzzyCompare(lockedAxis.z(), 0.0f))
- m_lockToAxisScale.setZ(lockedAxis.z());
- } else {
- m_lockToAxisScale = newScale;
+ }
+ if (altDown) {
+ QVector3D helperNormal = helperPlaneNormal();
+ QVector3D snapScale = newScale;
+ newScale = m_dragInitialScaleValue;
+ if (helperNormal.x() > 0.5f)
+ newScale.setX(snapScale.x());
+ else if (helperNormal.y() > 0.5f)
+ newScale.setY(snapScale.y());
+ else if (helperNormal.z() > 0.5f)
+ newScale.setZ(snapScale.z());
}
// Calculate the translate needed to keep opposite corner anchored
QMatrix4x4 ancestralTransform = EditorUtils::totalAncestralTransform(m_selectedEntity);
QVector3D ancestralScale =
- EditorUtils::totalAncestralScale(m_selectedEntity) * m_lockToAxisScale;
+ EditorUtils::totalAncestralScale(m_selectedEntity) * newScale;
QVector3D newHandleCornerTranslation = ancestralScale * m_dragHandleCornerTranslation;
EditorSceneItem *selectedItem = m_sceneItems.value(m_selectedEntity->id(), nullptr);
if (selectedItem)
@@ -975,7 +1014,7 @@ void EditorScene::dragScaleSelectedEntity(const QPoint &newPos, bool shiftDown,
m_undoHandler->createChangePropertyCommand(m_selectedEntity->objectName(),
EditorSceneItemComponentsModel::Transform,
- QStringLiteral("scale3D"), m_lockToAxisScale,
+ QStringLiteral("scale3D"), newScale,
m_selectedEntityTransform->scale3D(),
QStringLiteral("translation"), newTranslation,
m_selectedEntityTransform->translation(), true);
@@ -1644,6 +1683,8 @@ void EditorScene::createRootEntity()
m_dragHandleCornerAdjustments[6] = QVector3D( 1.0f, 1.0f, -1.0f);
m_dragHandleCornerAdjustments[7] = QVector3D( 1.0f, 1.0f, 1.0f);
+ m_dragEntitySnapOffsets.resize(dragCornerHandleCount);
+
// Active scene camera frustum visualization
m_activeSceneCameraFrustumData.frustumEntity = new Qt3DCore::QEntity(m_rootEntity);
m_activeSceneCameraFrustumData.viewVectorEntity = new Qt3DCore::QEntity(m_rootEntity);
@@ -2041,16 +2082,8 @@ void EditorScene::endSelectionHandling()
&& m_dragHandlesTransform->isEnabled()
&& (!cameraEntity || !m_cameraViewCenterSelected);
if (viewCenterDrag || entityDrag) {
- m_dragMode = DragTranslate;
- m_dragEntity = m_pickedEntity;
- if (cameraEntity) {
- if (viewCenterDrag)
- m_dragInitialTranslationValue = cameraEntity->viewCenter();
- else
- m_dragInitialTranslationValue = cameraEntity->position();
- } else {
- m_dragInitialTranslationValue = m_dragHandlesTransform->translation();
- }
+ // The mouse position passed to dragHandlePress is irrelevant in this case
+ dragHandlePress(DragTranslate, QPoint(0, 0), 0);
}
}
m_pickedEntity = nullptr;
@@ -2205,7 +2238,7 @@ void EditorScene::handleSelectionTransformChange()
void EditorScene::handlePickerPress(Qt3DRender::QPickEvent *event)
{
- if (m_dragMode == DragNone) {
+ if (m_dragMode == DragNone && m_mouseButton == Qt::LeftButton) {
Qt3DCore::QEntity *pressedEntity = qobject_cast<Qt3DCore::QEntity *>(sender()->parent());
// If pressedEntity is not enabled, it typically means the pressedEntity is a drag handle
// and the selection has changed to a different type of entity since the mouse press was
@@ -2241,6 +2274,7 @@ void EditorScene::handlePickerPress(Qt3DRender::QPickEvent *event)
if (lightData->visibleEntity == pressedEntity) {
pressedEntity = lightData->lightEntity;
select = true;
+ break;
}
}
} else if (pressedEntity->objectName() == sceneLoaderSubEntityName) {
@@ -2259,13 +2293,9 @@ void EditorScene::handlePickerPress(Qt3DRender::QPickEvent *event)
}
}
}
- if (select && !m_pickedEntity && m_mouseButton == Qt::LeftButton)
+ if (select && !m_pickedEntity)
QMetaObject::invokeMethod(this, "endSelectionHandling", Qt::QueuedConnection);
m_pickedEntity = pressedEntity;
- // Get the position of the picked entity, and copy it to m_snapToGridIntersection
- m_snapToGridIntersection = EditorUtils::entityTransform(m_pickedEntity)->translation();
- // Get the scale of the picked entity, and copy it to m_lockToAxisScale
- m_lockToAxisScale = EditorUtils::entityTransform(m_pickedEntity)->scale3D();
}
}
}
@@ -2289,6 +2319,7 @@ bool EditorScene::handleMouseRelease(QMouseEvent *event)
emit mouseRightButtonReleasedWithoutDragging();
}
}
+ m_cameraViewCenterSelected = false;
cancelDrag();
return false; // Never consume release event
}
@@ -2598,3 +2629,42 @@ void EditorScene::checkMultiSelectionHighlights(const QStringList &oldlist,
}
}
}
+
+QVector3D EditorScene::snapPosition(const QVector3D &worldPos, bool x, bool y, bool z)
+{
+ QVector3D newPos = worldPos;
+ float shortestLen = FLT_MAX;
+ int index = 0;
+ QVector3D snapPos;
+ // Snap nearest corner to grid intersection
+ for (int i = 0; i < dragCornerHandleCount; ++i) {
+ QVector3D corner = worldPos;
+ QVector3D currentPos = worldPos;
+ if (x) {
+ corner.setX(worldPos.x() + m_dragEntitySnapOffsets.at(i).x());
+ currentPos.setX(qRound(corner.x() / m_gridSize) * m_gridSize);
+ }
+ if (y) {
+ corner.setY(worldPos.y() + m_dragEntitySnapOffsets.at(i).y());
+ currentPos.setY(qRound(corner.y() / m_gridSize) * m_gridSize);
+ }
+ if (z) {
+ corner.setZ(worldPos.z() + m_dragEntitySnapOffsets.at(i).z());
+ currentPos.setZ(qRound(corner.z() / m_gridSize) * m_gridSize);
+ }
+ float len = (corner - currentPos).length();
+ if (len < shortestLen) {
+ shortestLen = len;
+ snapPos = currentPos;
+ index = i;
+ }
+ }
+ if (x)
+ newPos.setX(snapPos.x() - m_dragEntitySnapOffsets.at(index).x());
+ if (y)
+ newPos.setY(snapPos.y() - m_dragEntitySnapOffsets.at(index).y());
+ if (z)
+ newPos.setZ(snapPos.z() - m_dragEntitySnapOffsets.at(index).z());
+
+ return newPos;
+}
diff --git a/editorlib/src/editorscene.h b/editorlib/src/editorscene.h
index c1c0aa0..8aaa8f8 100644
--- a/editorlib/src/editorscene.h
+++ b/editorlib/src/editorscene.h
@@ -95,7 +95,8 @@ public:
DragNone = 0,
DragTranslate,
DragScale,
- DragRotate
+ DragRotate,
+ DragDebug // Can be used to debugging positions
};
Q_ENUM(DragMode)
@@ -308,6 +309,8 @@ public:
void setError(const QString &errorString);
Qt3DRender::QObjectPicker *createObjectPickerForEntity(Qt3DCore::QEntity *entity);
+ void showDebugHandle(bool show, int handleIndex = 0, const QVector3D &worldPosition = QVector3D());
+
public slots:
void clearSelectionBoxes(Qt3DCore::QEntity *skipEntity = nullptr);
@@ -381,7 +384,7 @@ private:
void createSceneLoaderChildPickers(Qt3DCore::QEntity *entity,
QList<Qt3DRender::QObjectPicker *> *pickers);
void checkMultiSelectionHighlights(const QStringList &oldlist, const QStringList &newlist);
-
+ QVector3D snapPosition(const QVector3D &worldPos, bool x, bool y, bool z);
private:
Qt3DCore::QEntity *m_rootEntity;
Qt3DCore::QEntity *m_componentCache;
@@ -444,7 +447,8 @@ private:
int m_dragHandleIndex;
DragMode m_dragMode;
QPoint m_previousMousePosition;
- QVector3D m_dragInitialTranslationValue;
+ QVector3D m_dragInitialEntityTranslationValue;
+ QVector3D m_dragInitialWorldTranslationValue;
QVector3D m_dragInitialScaleValue;
QQuaternion m_dragInitialRotationValue;
QVector3D m_dragInitialRotateCustomVector;
@@ -452,14 +456,13 @@ private:
QVector3D m_dragInitialHandleCornerTranslation;
QVector3D m_dragInitialCenterTranslation;
QVector3D m_dragHandleCornerTranslation;
+ QVector<QVector3D> m_dragEntitySnapOffsets;
QMatrix4x4 m_dragInitialHandleMatrix;
Qt3DCore::QEntity *m_dragEntity;
bool m_ignoringInitialDrag;
bool m_viewCenterLocked;
Qt3DCore::QEntity *m_pickedEntity;
float m_pickedDistance;
- QVector3D m_snapToGridIntersection;
- QVector3D m_lockToAxisScale;
int m_gridSize;
int m_duplicateCount;
Qt3DCore::QEntity *m_previousDuplicate;