Skip to content

Commit

Permalink
Merge pull request #404 from friction2d/pivot-align
Browse files Browse the repository at this point in the history
Support pivot alignment
  • Loading branch information
rodlie authored Dec 31, 2024
2 parents d46828b + 7485742 commit fff959c
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 16 deletions.
122 changes: 121 additions & 1 deletion src/app/GUI/extraactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void MainWindow::setupMenuExtras()
}
// align
{
const int alignTotal = 28;
const int alignTotal = 40;

const QString alignTextDefault = tr("Align %1 %2 Relative to %3");
const QString alignGeometry = tr("Geometry");
Expand Down Expand Up @@ -481,6 +481,126 @@ void MainWindow::setupMenuExtras()
alignBoth = false;
align = Qt::AlignVCenter;
break;
case 28: // Pivot alignment to Bounding Box - VCenter -----------------------------------------------------------------------------------
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::boundingBox;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignVCenter;
break;
case 29: // Pivot alignment to Bounding Box - HCenter
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::boundingBox;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignHCenter;
break;
case 30: // Pivot alignment to Bounding Box - Left
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::boundingBox;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignLeft;
break;
case 31: // Pivot alignment to Bounding Box - Right
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::boundingBox;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignRight;
break;
case 32: // Pivot alignment to Bounding Box - Top
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::boundingBox;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignTop;
break;
case 33: // Pivot alignment to Bounding Box - Bottom
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::boundingBox;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignBottom;
break;
case 34: // Pivot alignment to Scene - VCenter -----------------------------------------------------------------------------------
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::scene;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignVCenter;
break;
case 35: // Pivot alignment to Scene - HCenter
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::scene;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignHCenter;
break;
case 36: // Pivot alignment to Scene - Left
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::scene;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignLeft;
break;
case 37: // Pivot alignment to Scene - Right
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::scene;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignRight;
break;
case 38: // Pivot alignment to Scene - Top
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::scene;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignTop;
break;
case 39: // Pivot alignment to Scene - Bottom
alignString = alignVCenter;
pivotString = alignPivot;
relString = alignLast;
pivot = AlignPivot::pivotItself;
rel = AlignRelativeTo::scene;
iconString = alignVCenterIcon;
alignBoth = false;
align = Qt::AlignBottom;
break;
default:
return;
}
Expand Down
3 changes: 2 additions & 1 deletion src/app/friction.qss
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ QMenu::separator {
background-color: %4;
}

QMenu::item:disabled {
QMenu::item:disabled,
AlignWidget QPushButton::disabled {
background: transparent;
}

Expand Down
119 changes: 119 additions & 0 deletions src/core/Boxes/boundingbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,125 @@ void BoundingBox::alignPivot(const Qt::Alignment align, const QRectF& to) {
alignGeometry(QRectF(pivot, pivot), align, to);
}

void BoundingBox::alignPivotItself(const Qt::Alignment align,
const QRectF& to,
const AlignRelativeTo relativeTo,
const QPointF lastPivotAbsPos)
{
QPointF currentPivot = mTransformAnimator->getPivot();
QPointF currentPivotAbsPos = getPivotAbsPos();

QPointF lastSelectedPivotAbsPos = lastPivotAbsPos;

QPointF center = getRelCenterPosition();

switch (relativeTo) {
case AlignRelativeTo::scene:
switch (align) {
case Qt::AlignVCenter:
center.setX(currentPivot.x());
center.setY(currentPivot.y() - currentPivotAbsPos.y() + to.bottomRight().y()/2);
break;
case Qt::AlignHCenter:
center.setX(currentPivot.x() - currentPivotAbsPos.x() + to.bottomRight().x()/2);
center.setY(currentPivot.y());
break;
case Qt::AlignLeft:
center.setX(currentPivot.x() - currentPivotAbsPos.x());
center.setY(currentPivot.y());
break;
case Qt::AlignRight:
center.setX(currentPivot.x() + (to.topRight().x() - currentPivotAbsPos.x()));
center.setY(currentPivot.y());
break;
case Qt::AlignTop:
center.setX(currentPivot.x());
center.setY(currentPivot.y() - currentPivotAbsPos.y());
break;
case Qt::AlignBottom:
center.setX(currentPivot.x());
center.setY(currentPivot.y() + (to.bottomRight().y() - currentPivotAbsPos.y()));
break;
}
break;
case AlignRelativeTo::lastSelected:
switch (align) {
case Qt::AlignVCenter:
center.setX(currentPivot.x());
center.setY(currentPivot.y() - currentPivotAbsPos.y() + to.center().y());
break;
case Qt::AlignHCenter:
center.setX(currentPivot.x() - currentPivotAbsPos.x() + to.center().x());
center.setY(currentPivot.y());
break;
case Qt::AlignLeft:
center.setX(currentPivot.x() - currentPivotAbsPos.x() + to.topLeft().x());
center.setY(currentPivot.y());
break;
case Qt::AlignRight:
center.setX(currentPivot.x() + (to.topRight().x() - currentPivotAbsPos.x()));
center.setY(currentPivot.y());
break;
case Qt::AlignTop:
center.setX(currentPivot.x());
center.setY(currentPivot.y() - currentPivotAbsPos.y() + to.topLeft().y());
break;
case Qt::AlignBottom:
center.setX(currentPivot.x());
center.setY(currentPivot.y() + (to.bottomRight().y() - currentPivotAbsPos.y()));
break;
}
break;
case AlignRelativeTo::lastSelectedPivot:
switch (align) {
case Qt::AlignVCenter:
center.setX(currentPivot.x());
center.setY(currentPivot.y() - currentPivotAbsPos.y() + lastSelectedPivotAbsPos.y());
break;
case Qt::AlignHCenter:
center.setX(currentPivot.x() - currentPivotAbsPos.x() + lastSelectedPivotAbsPos.x());
center.setY(currentPivot.y());
break;
default:
center.setX(currentPivot.x());
center.setY(currentPivot.y());
break;
}
break;
case AlignRelativeTo::boundingBox:
switch (align) {
case Qt::AlignVCenter:
center.setX(currentPivot.x());
break;
case Qt::AlignHCenter:
center.setY(currentPivot.y());
break;
case Qt::AlignLeft:
center.setX(mRelRect.topLeft().x());
center.setY(currentPivot.y());
break;
case Qt::AlignRight:
center.setX(mRelRect.topRight().x());
center.setY(currentPivot.y());
break;
case Qt::AlignTop:
center.setX(currentPivot.x());
center.setY(mRelRect.topLeft().y());
break;
case Qt::AlignBottom:
center.setX(currentPivot.x());
center.setY(mRelRect.bottomLeft().y());
break;
}
break;
}

startPivotTransform();
mTransformAnimator->setPivotFixedTransform(center);
requestGlobalPivotUpdateIfSelected();
finishPivotTransform();
}

void BoundingBox::moveByAbs(const QPointF &trans) {
mTransformAnimator->moveByAbs(trans);
}
Expand Down
6 changes: 6 additions & 0 deletions src/core/Boxes/boundingbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@

class Canvas;

enum class AlignRelativeTo;

class QrealAction;
class MovablePoint;

Expand Down Expand Up @@ -298,6 +300,10 @@ class CORE_EXPORT BoundingBox : public eBoxOrSound {

void alignGeometry(const Qt::Alignment align, const QRectF& to);
void alignPivot(const Qt::Alignment align, const QRectF& to);
void alignPivotItself(const Qt::Alignment align,
const QRectF& to,
const AlignRelativeTo relativeTo,
const QPointF lastPivotAbsPos);

QMatrix getTotalTransform() const;

Expand Down
4 changes: 2 additions & 2 deletions src/core/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ class eKeyEvent;
enum class CtrlsMode : short;

enum class AlignPivot {
geometry, pivot
geometry, pivot, pivotItself
};

enum class AlignRelativeTo {
scene, lastSelected
scene, lastSelected, lastSelectedPivot, boundingBox
};

class CORE_EXPORT Canvas : public CanvasBase
Expand Down
26 changes: 20 additions & 6 deletions src/core/canvasselectedboxesactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,31 +851,45 @@ void Canvas::selectedPathsCombine() {

void Canvas::alignSelectedBoxes(const Qt::Alignment align,
const AlignPivot pivot,
const AlignRelativeTo relativeTo) {
if(mSelectedBoxes.isEmpty()) return;
const AlignRelativeTo relativeTo)
{
if (mSelectedBoxes.isEmpty()) { return; }
QRectF geometry;
BoundingBox* skip = nullptr;
switch(relativeTo) {
case AlignRelativeTo::scene:
case AlignRelativeTo::boundingBox:
geometry = QRectF(0., 0., mWidth, mHeight);
break;
case AlignRelativeTo::lastSelected:
if(!mLastSelectedBox) return;
if (!mLastSelectedBox) { return; }
skip = mLastSelectedBox;
geometry = mLastSelectedBox->getAbsBoundingRect();
break;
case AlignRelativeTo::lastSelectedPivot:
if (!mLastSelectedBox) { return; }
skip = mLastSelectedBox;
geometry = QRectF(mLastSelectedBox->getPivotAbsPos(),
mLastSelectedBox->getPivotAbsPos());
break;
}

pushUndoRedoName("align");
for(const auto &box : mSelectedBoxes) {
if(box == skip) continue;
pushUndoRedoName(pivot == AlignPivot::pivotItself ? "pivot align" : "box align");
for (const auto &box : mSelectedBoxes) {
if (box == skip) { continue; }
switch(pivot) {
case AlignPivot::pivot:
box->alignPivot(align, geometry);
break;
case AlignPivot::geometry:
box->alignGeometry(align, geometry);
break;
case AlignPivot::pivotItself:
box->alignPivotItself(align,
geometry,
relativeTo,
mLastSelectedBox->getPivotAbsPos());
break;
}
}
}
Loading

0 comments on commit fff959c

Please sign in to comment.