summaryrefslogtreecommitdiffstats
path: root/editorlib
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 /editorlib
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>
Diffstat (limited to 'editorlib')
-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;