Skip to content

Commit fb75d6a

Browse files
committed
Merge branch 'gizmos-v1-upstream-x-y-lines-v1.7' into gizmos-v1
2 parents bb36782 + 4e91cf1 commit fb75d6a

File tree

4 files changed

+152
-2
lines changed

4 files changed

+152
-2
lines changed

src/core/canvas.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,11 +1015,15 @@ bool Canvas::handleTransormationInputKeyEvent(const eKeyEvent &e)
10151015
} else if (e.fKey == Qt::Key_X) {
10161016
if (e.fAutorepeat) { return false; }
10171017
mValueInput.switchXOnlyMode();
1018+
const bool linesChanged = updateLineGizmoVisibility();
10181019
updateTransformation(e);
1020+
if (linesChanged) { emit requestUpdate(); }
10191021
} else if (e.fKey == Qt::Key_Y) {
10201022
if (e.fAutorepeat) { return false; }
10211023
mValueInput.switchYOnlyMode();
1024+
const bool linesChanged = updateLineGizmoVisibility();
10221025
updateTransformation(e);
1026+
if (linesChanged) { emit requestUpdate(); }
10231027
} else { return false; }
10241028
return true;
10251029
}

src/core/canvas.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,10 @@ class CORE_EXPORT Canvas : public CanvasBase
771771
void setRotateHandleHover(bool hovered);
772772
void setGizmosSuppressed(bool suppressed);
773773

774+
bool shouldShowXLineGizmo() const;
775+
bool shouldShowYLineGizmo() const;
776+
bool updateLineGizmoVisibility();
777+
774778
void updateRotateHandleGeometry(qreal invScale);
775779

776780
bool tryStartRotateWithGizmo(const eMouseEvent &e,

src/core/canvasgizmos.cpp

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,63 @@ void Canvas::renderGizmos(SkCanvas * const canvas,
3333
const float invZoom)
3434
{
3535
updateRotateHandleGeometry(qInvZoom);
36+
auto drawAxisLine = [&](const Gizmos::LineGeometry &geom,
37+
const QColor &baseColor,
38+
Gizmos::AxisConstraint axis,
39+
bool hovered,
40+
bool horizontal) {
41+
if (!geom.visible || geom.strokeWidth <= 0.0) { return; }
42+
43+
const bool active = (mGizmos.fState.axisConstraint == axis);
44+
QColor color = baseColor;
45+
if (active) {
46+
color = color.lighter(135);
47+
} else if (hovered) {
48+
color = color.lighter(120);
49+
}
50+
51+
const qreal strokeAlpha = (active || hovered)
52+
? mGizmos.fTheme.colorAlphaFillHover
53+
: mGizmos.fTheme.colorAlphaFillNormal;
54+
color.setAlpha(static_cast<int>(strokeAlpha));
55+
56+
SkPaint linePaint;
57+
linePaint.setAntiAlias(true);
58+
linePaint.setStyle(SkPaint::kStroke_Style);
59+
linePaint.setStrokeCap(SkPaint::kRound_Cap);
60+
linePaint.setStrokeWidth(toSkScalar(geom.strokeWidth));
61+
linePaint.setColor(toSkColor(color));
62+
63+
QPointF startPoint = geom.start;
64+
QPointF endPoint = geom.end;
65+
66+
SkIRect deviceClip;
67+
if (canvas->getDeviceClipBounds(&deviceClip)) {
68+
SkRect deviceRect = SkRect::Make(deviceClip);
69+
SkMatrix invMatrix;
70+
if (canvas->getTotalMatrix().invert(&invMatrix)) {
71+
SkRect worldRect = invMatrix.mapRect(deviceRect);
72+
if (horizontal) {
73+
startPoint.setX(worldRect.left());
74+
startPoint.setY(geom.start.y());
75+
endPoint.setX(worldRect.right());
76+
endPoint.setY(geom.start.y());
77+
} else {
78+
startPoint.setY(worldRect.top());
79+
endPoint.setY(worldRect.bottom());
80+
startPoint.setX(geom.start.x());
81+
endPoint.setX(geom.start.x());
82+
}
83+
}
84+
}
85+
86+
canvas->drawLine(toSkScalar(startPoint.x()),
87+
toSkScalar(startPoint.y()),
88+
toSkScalar(endPoint.x()),
89+
toSkScalar(endPoint.y()),
90+
linePaint);
91+
};
92+
3693

3794
if (mGizmos.fState.rotateHandleVisible) {
3895
if (mGizmos.fState.showRotate) {
@@ -257,7 +314,6 @@ void Canvas::renderGizmos(SkCanvas * const canvas,
257314
canvas->drawOval(skRect, borderPaint);
258315
}
259316
};
260-
261317
drawAxisRect(Gizmos::AxisConstraint::Y,
262318
mGizmos.fState.axisYGeom,
263319
QColor(mGizmos.fTheme.colorY.red(), mGizmos.fTheme.colorY.green(), mGizmos.fTheme.colorY.blue(),
@@ -291,6 +347,17 @@ void Canvas::renderGizmos(SkCanvas * const canvas,
291347
QColor(mGizmos.fTheme.colorX.red(), mGizmos.fTheme.colorX.green(), mGizmos.fTheme.colorX.blue(),
292348
mGizmos.fState.shearXHovered ? mGizmos.fTheme.colorAlphaFillHover : mGizmos.fTheme.colorAlphaFillNormal));
293349
}
350+
351+
drawAxisLine(mGizmos.fState.xLineGeom,
352+
mGizmos.fTheme.colorX,
353+
Gizmos::AxisConstraint::X,
354+
mGizmos.fState.axisXHovered,
355+
true);
356+
drawAxisLine(mGizmos.fState.yLineGeom,
357+
mGizmos.fTheme.colorY,
358+
Gizmos::AxisConstraint::Y,
359+
mGizmos.fState.axisYHovered,
360+
false);
294361
}
295362

296363
void Canvas::setGizmoVisibility(const Gizmos::Interact &ti,
@@ -439,10 +506,55 @@ void Canvas::setRotateHandleHover(bool hovered)
439506
emit requestUpdate();
440507
}
441508

509+
bool Canvas::shouldShowXLineGizmo() const
510+
{
511+
if (mValueInput.xOnlyMode()) {
512+
return true;
513+
}
514+
return mGizmos.fState.gizmosSuppressed &&
515+
mGizmos.fState.axisHandleActive &&
516+
mGizmos.fState.axisConstraint == Gizmos::AxisConstraint::X;
517+
}
518+
519+
bool Canvas::shouldShowYLineGizmo() const
520+
{
521+
if (mValueInput.yOnlyMode()) {
522+
return true;
523+
}
524+
return mGizmos.fState.gizmosSuppressed &&
525+
mGizmos.fState.axisHandleActive &&
526+
mGizmos.fState.axisConstraint == Gizmos::AxisConstraint::Y;
527+
}
528+
529+
bool Canvas::updateLineGizmoVisibility()
530+
{
531+
const bool desiredX = shouldShowXLineGizmo();
532+
const bool desiredY = shouldShowYLineGizmo();
533+
534+
bool changed = false;
535+
if (mGizmos.fState.xLineGeom.visible != desiredX) {
536+
mGizmos.fState.xLineGeom.visible = desiredX;
537+
changed = true;
538+
}
539+
if (mGizmos.fState.yLineGeom.visible != desiredY) {
540+
mGizmos.fState.yLineGeom.visible = desiredY;
541+
changed = true;
542+
}
543+
return changed;
544+
}
545+
442546
void Canvas::setGizmosSuppressed(bool suppressed)
443547
{
444-
if (mGizmos.fState.gizmosSuppressed == suppressed) { return; }
548+
if (mGizmos.fState.gizmosSuppressed == suppressed) {
549+
if (updateLineGizmoVisibility()) {
550+
emit requestUpdate();
551+
}
552+
return;
553+
}
554+
445555
mGizmos.fState.gizmosSuppressed = suppressed;
556+
updateLineGizmoVisibility();
557+
446558
if (suppressed) {
447559
mGizmos.fState.rotateHandleHovered = false;
448560
mGizmos.fState.axisXHovered = false;
@@ -454,6 +566,7 @@ void Canvas::setGizmosSuppressed(bool suppressed)
454566
mGizmos.fState.shearXHovered = false;
455567
mGizmos.fState.shearYHovered = false;
456568
}
569+
457570
emit requestUpdate();
458571
}
459572

@@ -482,6 +595,8 @@ void Canvas::updateRotateHandleGeometry(qreal invScale)
482595
mGizmos.fState.scaleUniformGeom = Gizmos::ScaleGeometry();
483596
mGizmos.fState.shearXGeom = Gizmos::ShearGeometry();
484597
mGizmos.fState.shearYGeom = Gizmos::ShearGeometry();
598+
mGizmos.fState.xLineGeom = Gizmos::LineGeometry();
599+
mGizmos.fState.yLineGeom = Gizmos::LineGeometry();
485600

486601
mGizmos.fState.axisConstraint = Gizmos::AxisConstraint::None;
487602
mGizmos.fState.scaleConstraint = Gizmos::ScaleHandle::None;
@@ -525,6 +640,10 @@ void Canvas::updateRotateHandleGeometry(qreal invScale)
525640
const qreal axisHeightWorld = mGizmos.fConfig.axisHeightPx * invScale;
526641
const qreal axisGapYWorld = mGizmos.fConfig.axisYOffsetPx * invScale;
527642
const qreal axisGapXWorld = mGizmos.fConfig.axisXOffsetPx * invScale;
643+
const qreal xLineLengthWorld = mGizmos.fConfig.xLineLengthPx * invScale;
644+
const qreal xLineStrokeWorld = mGizmos.fConfig.xLineStrokePx * invScale;
645+
const qreal yLineLengthWorld = mGizmos.fConfig.yLineLengthPx * invScale;
646+
const qreal yLineStrokeWorld = mGizmos.fConfig.yLineStrokePx * invScale;
528647

529648
// const qreal anchorOffset = axisWidthWorld * 0.5;
530649
const qreal anchorOffset = 2.0 * invScale;
@@ -626,6 +745,15 @@ void Canvas::updateRotateHandleGeometry(qreal invScale)
626745
pivot + QPointF((mGizmos.fConfig.axisUniformWidthPx - mGizmos.fConfig.axisUniformChamferPx) * invScale, - mGizmos.fConfig.axisUniformOffsetPx * invScale)
627746
};
628747

748+
mGizmos.fState.xLineGeom.start = pivot;
749+
mGizmos.fState.xLineGeom.end = pivot + QPointF(xLineLengthWorld, 0.0);
750+
mGizmos.fState.xLineGeom.strokeWidth = xLineStrokeWorld;
751+
752+
mGizmos.fState.yLineGeom.start = pivot;
753+
mGizmos.fState.yLineGeom.end = pivot + QPointF(0.0, yLineLengthWorld);
754+
mGizmos.fState.yLineGeom.strokeWidth = yLineStrokeWorld;
755+
756+
updateLineGizmoVisibility();
629757
const qreal rotateOffsetWorld = mGizmos.fState.axisYGeom.size.width() * 0.5;
630758
mGizmos.fState.rotateHandleRadius = baseRotateRadiusWorld + rotateOffsetWorld;
631759

src/core/gizmos.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ namespace Friction
9696
QVector<QPointF> polygonPoints;
9797
};
9898

99+
struct LineGeometry
100+
{
101+
QPointF start;
102+
QPointF end;
103+
qreal strokeWidth = 0.0;
104+
bool visible = false;
105+
};
106+
99107
struct Config
100108
{
101109
qreal rotateSweepDeg = 90.0; // default sweep of gizmo arc
@@ -115,6 +123,10 @@ namespace Friction
115123
qreal shearRadiusPx = 6.0; // shear gizmo circle radius in screen pixels
116124
// TODO? this is not used
117125
qreal shearGapPx = 2.0; // gap between scale and shear gizmos in screen pixels
126+
qreal xLineLengthPx = 100.0; // length of the XLine gizmo in screen pixels
127+
qreal xLineStrokePx = 2.0; // stroke thickness for the XLine gizmo in screen pixels
128+
qreal yLineLengthPx = 100.0; // length of the YLine gizmo in screen pixels
129+
qreal yLineStrokePx = 2.0; // stroke thickness for the YLine gizmo in screen pixels
118130
};
119131

120132
struct Theme
@@ -153,6 +165,8 @@ namespace Friction
153165
ScaleGeometry scaleUniformGeom;
154166
ShearGeometry shearXGeom;
155167
ShearGeometry shearYGeom;
168+
LineGeometry xLineGeom;
169+
LineGeometry yLineGeom;
156170
bool axisXHovered = false;
157171
bool axisYHovered = false;
158172
bool axisUniformHovered = false;

0 commit comments

Comments
 (0)