forked from qt-creator/qt-creator
QmlDesigner: Implement grid zooming
Grid zooms in and out according to camera zoom so that grid spacing is neither too condense nor too sparse. Also changed the grid color to be a bit darker and few other small tweaks. PS: if the view camera is panned, the grid will not work correctly. This is due to issues with the camera zoom calculations and is not part of this commit. Task-number: QDS-1566 Change-Id: Ib08d5387b028b8d870df9ecf88a5766eae5a509e Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -79,9 +79,11 @@ Window {
|
|||||||
{"usePerspective": usePerspective,
|
{"usePerspective": usePerspective,
|
||||||
"showSceneLight": showEditLight,
|
"showSceneLight": showEditLight,
|
||||||
"importScene": activeScene,
|
"importScene": activeScene,
|
||||||
|
"cameraZoomFactor": cameraControl._zoomFactor,
|
||||||
"z": 1});
|
"z": 1});
|
||||||
editView.usePerspective = Qt.binding(function() {return usePerspective;});
|
editView.usePerspective = Qt.binding(function() {return usePerspective;});
|
||||||
editView.showSceneLight = Qt.binding(function() {return showEditLight;});
|
editView.showSceneLight = Qt.binding(function() {return showEditLight;});
|
||||||
|
editView.cameraZoomFactor = Qt.binding(function() {return cameraControl._zoomFactor;});
|
||||||
|
|
||||||
selectionBoxes.length = 0;
|
selectionBoxes.length = 0;
|
||||||
}
|
}
|
||||||
|
@@ -32,11 +32,13 @@ Node {
|
|||||||
|
|
||||||
property alias lines: gridGeometry.lines
|
property alias lines: gridGeometry.lines
|
||||||
property alias step: gridGeometry.step
|
property alias step: gridGeometry.step
|
||||||
|
property alias subdivAlpha: subGridMaterial.opacity
|
||||||
|
|
||||||
rotation.x: 90
|
rotation.x: 90
|
||||||
|
|
||||||
// Note: Only one instance of HelperGrid is supported, as the geometry names are fixed
|
// Note: Only one instance of HelperGrid is supported, as the geometry names are fixed
|
||||||
Model {
|
|
||||||
|
Model { // Main grid lines
|
||||||
geometry: GridGeometry {
|
geometry: GridGeometry {
|
||||||
id: gridGeometry
|
id: gridGeometry
|
||||||
name: "3D Edit View Helper Grid"
|
name: "3D Edit View Helper Grid"
|
||||||
@@ -45,13 +47,32 @@ Node {
|
|||||||
materials: [
|
materials: [
|
||||||
DefaultMaterial {
|
DefaultMaterial {
|
||||||
id: mainGridMaterial
|
id: mainGridMaterial
|
||||||
emissiveColor: "#cccccc"
|
emissiveColor: "#aaaaaa"
|
||||||
lighting: DefaultMaterial.NoLighting
|
lighting: DefaultMaterial.NoLighting
|
||||||
cullingMode: Material.DisableCulling
|
cullingMode: Material.DisableCulling
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Model {
|
|
||||||
|
Model { // Subdivision lines
|
||||||
|
geometry: GridGeometry {
|
||||||
|
lines: gridGeometry.lines
|
||||||
|
step: gridGeometry.step
|
||||||
|
isSubdivision: true
|
||||||
|
name: "3D Edit View Helper Grid subdivisions"
|
||||||
|
}
|
||||||
|
|
||||||
|
materials: [
|
||||||
|
DefaultMaterial {
|
||||||
|
id: subGridMaterial
|
||||||
|
emissiveColor: mainGridMaterial.emissiveColor
|
||||||
|
lighting: DefaultMaterial.NoLighting
|
||||||
|
cullingMode: Material.DisableCulling
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Model { // Z Axis
|
||||||
geometry: GridGeometry {
|
geometry: GridGeometry {
|
||||||
lines: gridGeometry.lines
|
lines: gridGeometry.lines
|
||||||
step: gridGeometry.step
|
step: gridGeometry.step
|
||||||
@@ -67,7 +88,7 @@ Node {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Model {
|
Model { // X Axis
|
||||||
rotation.z: 90
|
rotation.z: 90
|
||||||
geometry: GridGeometry {
|
geometry: GridGeometry {
|
||||||
lines: gridGeometry.lines
|
lines: gridGeometry.lines
|
||||||
|
@@ -35,16 +35,29 @@ View3D {
|
|||||||
property alias sceneHelpers: sceneHelpers
|
property alias sceneHelpers: sceneHelpers
|
||||||
property alias perpectiveCamera: scenePerspectiveCamera
|
property alias perpectiveCamera: scenePerspectiveCamera
|
||||||
property alias orthoCamera: sceneOrthoCamera
|
property alias orthoCamera: sceneOrthoCamera
|
||||||
|
property double cameraZoomFactor: .55;
|
||||||
|
|
||||||
|
// Empirical cameraZoomFactor values at which the grid zoom level is doubled. The values are
|
||||||
|
// approximately uniformally distributed over the non-linear range of cameraZoomFactor.
|
||||||
|
readonly property var grid_thresholds: [0.1, 0.265, 0.55, 1.10, 2.35, 4.9, 10.0, 20.5, 42.0, 85.0, 999999.0]
|
||||||
|
property var thresIdx: 1
|
||||||
|
property var thresPerc: 1.0 // percentage of cameraZoomFactor to the current grid zoom threshold (0.0 - 1.0)
|
||||||
|
|
||||||
camera: usePerspective ? scenePerspectiveCamera : sceneOrthoCamera
|
camera: usePerspective ? scenePerspectiveCamera : sceneOrthoCamera
|
||||||
|
|
||||||
|
onCameraZoomFactorChanged: {
|
||||||
|
thresIdx = Math.max(1, grid_thresholds.findIndex(v => v > cameraZoomFactor));
|
||||||
|
thresPerc = (grid_thresholds[thresIdx] - cameraZoomFactor) / (grid_thresholds[thresIdx] - grid_thresholds[thresIdx - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
Node {
|
Node {
|
||||||
id: sceneHelpers
|
id: sceneHelpers
|
||||||
|
|
||||||
HelperGrid {
|
HelperGrid {
|
||||||
id: helperGrid
|
id: helperGrid
|
||||||
lines: 50
|
lines: 20 + Math.round((1 - thresPerc) * 20);
|
||||||
step: 50
|
step: 100 * grid_thresholds[0] * Math.pow(2, thresIdx - 1);
|
||||||
|
subdivAlpha: thresPerc;
|
||||||
}
|
}
|
||||||
|
|
||||||
PointLight {
|
PointLight {
|
||||||
|
@@ -114,16 +114,18 @@ QSSGRenderGraphObject *GridGeometry::updateSpatialNode(QSSGRenderGraphObject *no
|
|||||||
|
|
||||||
void GridGeometry::fillVertexData(QByteArray &vertexData)
|
void GridGeometry::fillVertexData(QByteArray &vertexData)
|
||||||
{
|
{
|
||||||
const int size = m_isCenterLine
|
const int numSubdivs = 1; // number of subdivision lines (i.e. lines between main grid lines)
|
||||||
? int(sizeof(float)) * 3 * 2
|
const int vtxSize = int(sizeof(float)) * 3 * 2;
|
||||||
: 4 * m_lines * int(sizeof(float)) * 3 * 2;
|
const int size = m_isCenterLine ? vtxSize
|
||||||
|
: m_isSubdivision ? 4 * m_lines * vtxSize * numSubdivs
|
||||||
|
: 4 * m_lines * vtxSize;
|
||||||
vertexData.resize(size);
|
vertexData.resize(size);
|
||||||
float *dataPtr = reinterpret_cast<float *>(vertexData.data());
|
float *dataPtr = reinterpret_cast<float *>(vertexData.data());
|
||||||
|
|
||||||
float y0 = -float(m_lines) * m_step;
|
|
||||||
float x0 = -float(m_lines) * m_step;
|
float x0 = -float(m_lines) * m_step;
|
||||||
float y1 = -y0;
|
float y0 = x0;
|
||||||
float x1 = -x0;
|
float x1 = -x0;
|
||||||
|
float y1 = x1;
|
||||||
|
|
||||||
if (m_isCenterLine) {
|
if (m_isCenterLine) {
|
||||||
// start position
|
// start position
|
||||||
@@ -134,6 +136,28 @@ void GridGeometry::fillVertexData(QByteArray &vertexData)
|
|||||||
dataPtr[3] = 0.f;
|
dataPtr[3] = 0.f;
|
||||||
dataPtr[4] = y1;
|
dataPtr[4] = y1;
|
||||||
dataPtr[5] = 0.f;
|
dataPtr[5] = 0.f;
|
||||||
|
} else {
|
||||||
|
// Lines are created so that bounding box can later be calculated from first and last vertex
|
||||||
|
if (m_isSubdivision) {
|
||||||
|
const float subdivStep = m_step / float(numSubdivs + 1);
|
||||||
|
const int subdivMainLines = m_lines * 2;
|
||||||
|
auto generateSubLines = [&](float x0, float y0, float x1, float y1, bool vertical) {
|
||||||
|
for (int i = 0; i < subdivMainLines; ++i) {
|
||||||
|
for (int j = 1; j <= numSubdivs; ++j) {
|
||||||
|
// start position
|
||||||
|
dataPtr[0] = vertical ? x0 + i * m_step + j * subdivStep : x0;
|
||||||
|
dataPtr[1] = vertical ? y0 : y0 + i * m_step + j * subdivStep;
|
||||||
|
dataPtr[2] = .0f;
|
||||||
|
// end position
|
||||||
|
dataPtr[3] = vertical ? x0 + i * m_step + j * subdivStep : x1;
|
||||||
|
dataPtr[4] = vertical ? y1 : y0 + i * m_step + j * subdivStep;
|
||||||
|
dataPtr[5] = .0f;
|
||||||
|
dataPtr += 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
generateSubLines(x0, y0, x1, y1, true);
|
||||||
|
generateSubLines(x0, y0, x1, y1, false);
|
||||||
} else {
|
} else {
|
||||||
auto generateLines = [this, &dataPtr](float x0, float y0, float x1, float y1, bool vertical) {
|
auto generateLines = [this, &dataPtr](float x0, float y0, float x1, float y1, bool vertical) {
|
||||||
for (int i = 0; i < m_lines; ++i) {
|
for (int i = 0; i < m_lines; ++i) {
|
||||||
@@ -148,13 +172,12 @@ void GridGeometry::fillVertexData(QByteArray &vertexData)
|
|||||||
dataPtr += 6;
|
dataPtr += 6;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lines are created so that bounding box can later be calculated from first and last vertex
|
|
||||||
generateLines(x0, y0, x1, y1, true);
|
generateLines(x0, y0, x1, y1, true);
|
||||||
generateLines(x0, y0, x1, y1, false);
|
generateLines(x0, y0, x1, y1, false);
|
||||||
generateLines(x0, m_step, x1, y1, false);
|
generateLines(x0, m_step, x1, y1, false);
|
||||||
generateLines(m_step, y0, x1, y1, true);
|
generateLines(m_step, y0, x1, y1, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -35,9 +35,11 @@ namespace Internal {
|
|||||||
class GridGeometry : public QQuick3DGeometry
|
class GridGeometry : public QQuick3DGeometry
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(int lines READ lines WRITE setLines NOTIFY linesChanged)
|
Q_PROPERTY(int lines READ lines WRITE setLines NOTIFY linesChanged)
|
||||||
Q_PROPERTY(float step READ step WRITE setStep NOTIFY stepChanged)
|
Q_PROPERTY(float step READ step WRITE setStep NOTIFY stepChanged)
|
||||||
Q_PROPERTY(bool isCenterLine READ isCenterLine WRITE setIsCenterLine NOTIFY isCenterLineChanged)
|
Q_PROPERTY(bool isCenterLine READ isCenterLine WRITE setIsCenterLine NOTIFY isCenterLineChanged)
|
||||||
|
Q_PROPERTY(bool isSubdivision MEMBER m_isSubdivision)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GridGeometry();
|
GridGeometry();
|
||||||
@@ -63,9 +65,10 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void fillVertexData(QByteArray &vertexData);
|
void fillVertexData(QByteArray &vertexData);
|
||||||
|
|
||||||
int m_lines = 1000;
|
int m_lines = 20; // number of lines on 1 side of an axis (so total number of grid lines in 1 direction = 2 * m_lines + 1)
|
||||||
float m_step = .1f;
|
float m_step = .1f;
|
||||||
bool m_isCenterLine = false;
|
bool m_isCenterLine = false;
|
||||||
|
bool m_isSubdivision = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user