@@ -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
296363void 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+
442546void 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
0 commit comments