Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
43a01cc
Grid: first working version
pgilfernandez Oct 16, 2025
cf2898c
Grid: use colorAnimationButton for grid color selection
pgilfernandez Oct 16, 2025
fae7130
Grid: mayor lines now use independent color and alpha
pgilfernandez Oct 16, 2025
fed233a
Grid: "show grid" is now a menu option
pgilfernandez Oct 16, 2025
122e94e
Grid: working persistence for settings
pgilfernandez Oct 16, 2025
fb10f82
Grid: fix working persistence for settings
pgilfernandez Oct 16, 2025
8af7fc0
Grid: add option to draw grid on top or behind
pgilfernandez Oct 16, 2025
69e966f
Grid: View / Grid menu rearranged and Grid settings tweaks
pgilfernandez Oct 17, 2025
12d05b7
Grid: grid visual options get saved for next sessions (show, snap and…
pgilfernandez Oct 17, 2025
1ea91c1
Grid: settings labels tweaking
pgilfernandez Oct 17, 2025
6a36f09
Grid: added snapping capabilities to nodes and pivot points
pgilfernandez Oct 17, 2025
648e533
Grid: simplify version
pgilfernandez Oct 17, 2025
79ca149
Grid: divide "Major line every" in X and Y for more flexibility
pgilfernandez Oct 17, 2025
18fce0f
Grid: fix simplify version commit
pgilfernandez Oct 17, 2025
6e8b9c4
Grid: simplify documentrw.cpp
pgilfernandez Oct 17, 2025
5a328c7
Grid: add rectangle, circle and path now stick to the grid at creation
pgilfernandez Oct 21, 2025
e1888fc
Grid: tangents of "add path" now stick to grid
pgilfernandez Oct 21, 2025
46d128e
Grid: simplify default grid color definitions
pgilfernandez Oct 22, 2025
d3a7d0b
Grid: rearrange dialog parameters
pgilfernandez Oct 22, 2025
f58f9b7
Grid: update default values
pgilfernandez Oct 22, 2025
5819123
Grid: add canvas corners, midpoints and center as snapping points
pgilfernandez Oct 22, 2025
871547a
Grid: more Grid Settings dialog tweaking
pgilfernandez Oct 22, 2025
bf1cf1d
Grid: fix originX default as Scene default is 1920px
pgilfernandez Oct 22, 2025
f7fe636
Grid: make dialog to stay on top while allow to use Friction normally
pgilfernandez Oct 23, 2025
9e7c856
Grid: fix for Windows not correctly compiling the new feature
pgilfernandez Oct 23, 2025
b50cae2
add the new Grid icon
pgilfernandez Oct 24, 2025
12d0cc1
Grid: add snapping support for bounding box corners
pgilfernandez Oct 24, 2025
cac20fb
Grid: add "snap radius" to rectangle, circle and path creation
pgilfernandez Oct 24, 2025
a14e21e
Grid: added "snap to boxes" and "snap to nodes"
pgilfernandez Oct 25, 2025
47c8141
Grid: "pivot" and "bounding box" points are now optional
pgilfernandez Oct 25, 2025
729c7ed
Grid: anchors now are optional, "pivot" and "bounding box". Added "no…
pgilfernandez Oct 25, 2025
4e70b79
Grid: add "snap to pivots" option
pgilfernandez Oct 25, 2025
0931d01
Grid: added bounding box midpoints to "snap to boxes"
pgilfernandez Oct 25, 2025
6c93fed
Grid: simple menu items tweaks
pgilfernandez Oct 25, 2025
a3f8318
Grid: add a global "Snapping" switch
pgilfernandez Oct 25, 2025
cce5036
Grid: add bounding box points of selected object as snapping points f…
pgilfernandez Oct 26, 2025
f5e5fcc
Grid: some fixes from comments
pgilfernandez Oct 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/app/GUI/canvaswindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <QComboBox>
#include <QApplication>
#include <QTransform>

#include "mainwindow.h"
#include "GUI/BoxesList/boxscroller.h"
Expand Down Expand Up @@ -173,6 +174,10 @@ void CanvasWindow::renderSk(SkCanvas * const canvas)
{
qreal pixelRatio = this->devicePixelRatioF();
if (mCurrentCanvas) {
const QTransform worldToScreen(mViewTransform.m11(), mViewTransform.m12(), 0.0,
mViewTransform.m21(), mViewTransform.m22(), 0.0,
mViewTransform.dx(), mViewTransform.dy(), 1.0);
mCurrentCanvas->setWorldToScreen(worldToScreen, pixelRatio);
canvas->save();
mCurrentCanvas->renderSk(canvas,
rect(),
Expand Down
124 changes: 124 additions & 0 deletions src/app/GUI/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <iostream>
#include <QClipboard>
#include <QMimeData>
#include <QSignalBlocker>

#include "GUI/edialogs.h"
#include "dialogs/applyexpressiondialog.h"
Expand Down Expand Up @@ -76,6 +77,7 @@
#include "widgets/assetswidget.h"
#include "dialogs/adjustscenedialog.h"
#include "dialogs/commandpalette.h"
#include "dialogs/gridsettingsdialog.h"

using namespace Friction;

Expand Down Expand Up @@ -117,6 +119,18 @@ MainWindow::MainWindow(Document& document,
, mInvertSelAct(nullptr)
, mClearSelAct(nullptr)
, mAddKeyAct(nullptr)
, mShowGridAct(nullptr)
, mSnappingAct(nullptr)
, mSnapToGridAct(nullptr)
, mSnapToCanvasAct(nullptr)
, mSnapToBoxesAct(nullptr)
, mSnapToNodesAct(nullptr)
, mSnapToPivotsAct(nullptr)
, mSnapAnchorPivotAct(nullptr)
, mSnapAnchorBoundsAct(nullptr)
, mSnapAnchorNodesAct(nullptr)
, mGridSettingsAct(nullptr)
, mGridDrawOnTopAct(nullptr)
, mAddToQueAct(nullptr)
, mViewFullScreenAct(nullptr)
, mFontWidget(nullptr)
Expand Down Expand Up @@ -160,6 +174,13 @@ MainWindow::MainWindow(Document& document,
Q_ASSERT(!sInstance);
sInstance = this;

connect(&mDocument, &Document::gridSettingsChanged,
this, &MainWindow::onGridSettingsChanged);
connect(&mDocument, &Document::gridSnapEnabledChanged,
this, &MainWindow::onGridSnapEnabledChanged);
connect(&mDocument, &Document::snappingActiveChanged,
this, &MainWindow::onSnappingActiveChanged);

setWindowIcon(QIcon::fromTheme(AppSupport::getAppID()));
setContextMenuPolicy(Qt::NoContextMenu);

Expand Down Expand Up @@ -208,6 +229,109 @@ BoundingBox *MainWindow::getCurrentBox()
return box;
}

void MainWindow::openGridSettingsDialog()
{
auto dialog = new GridSettingsDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setWindowTitle(tr("Grid Settings"));
dialog->setSettings(mDocument.gridController().settings);
connect(dialog, &GridSettingsDialog::applyRequested,
this, [this](Friction::Core::GridSettings settings, bool saveDefaults) {
settings.enabled = mDocument.gridController().settings.enabled;
mDocument.setGridSettings(settings);
if (saveDefaults) {
mDocument.saveGridSettingsAsDefault(mDocument.gridController().settings);
}
});
connect(dialog, &QDialog::accepted,
this, [this, dialog]() {
auto settings = dialog->settings();
settings.enabled = mDocument.gridController().settings.enabled;
mDocument.setGridSettings(settings);
if (dialog->saveAsDefault()) {
mDocument.saveGridSettingsAsDefault(mDocument.gridController().settings);
}
});
dialog->show();
}

void MainWindow::onGridSettingsChanged(const Friction::Core::GridSettings& settings)
{
onGridSnapEnabledChanged(settings.enabled);
if (mShowGridAct) {
QSignalBlocker blocker(mShowGridAct);
if (mShowGridAct->isChecked() != settings.show) {
mShowGridAct->setChecked(settings.show);
}
}
if (mSnapToCanvasAct) {
QSignalBlocker blocker(mSnapToCanvasAct);
if (mSnapToCanvasAct->isChecked() != settings.snapToCanvas) {
mSnapToCanvasAct->setChecked(settings.snapToCanvas);
}
}
if (mSnapToBoxesAct) {
QSignalBlocker blocker(mSnapToBoxesAct);
if (mSnapToBoxesAct->isChecked() != settings.snapToBoxes) {
mSnapToBoxesAct->setChecked(settings.snapToBoxes);
}
}
if (mSnapToNodesAct) {
QSignalBlocker blocker(mSnapToNodesAct);
if (mSnapToNodesAct->isChecked() != settings.snapToNodes) {
mSnapToNodesAct->setChecked(settings.snapToNodes);
}
}
if (mSnapToPivotsAct) {
QSignalBlocker blocker(mSnapToPivotsAct);
if (mSnapToPivotsAct->isChecked() != settings.snapToPivots) {
mSnapToPivotsAct->setChecked(settings.snapToPivots);
}
}
if (mSnapAnchorPivotAct) {
QSignalBlocker blocker(mSnapAnchorPivotAct);
if (mSnapAnchorPivotAct->isChecked() != settings.snapAnchorPivot) {
mSnapAnchorPivotAct->setChecked(settings.snapAnchorPivot);
}
}
if (mSnapAnchorBoundsAct) {
QSignalBlocker blocker(mSnapAnchorBoundsAct);
if (mSnapAnchorBoundsAct->isChecked() != settings.snapAnchorBounds) {
mSnapAnchorBoundsAct->setChecked(settings.snapAnchorBounds);
}
}
if (mSnapAnchorNodesAct) {
QSignalBlocker blocker(mSnapAnchorNodesAct);
if (mSnapAnchorNodesAct->isChecked() != settings.snapAnchorNodes) {
mSnapAnchorNodesAct->setChecked(settings.snapAnchorNodes);
}
}
if (mGridDrawOnTopAct) {
QSignalBlocker blocker(mGridDrawOnTopAct);
if (mGridDrawOnTopAct->isChecked() != settings.drawOnTop) {
mGridDrawOnTopAct->setChecked(settings.drawOnTop);
}
}
}

void MainWindow::onGridSnapEnabledChanged(bool enabled)
{
if (!mSnapToGridAct) { return; }
QSignalBlocker blocker(mSnapToGridAct);
if (mSnapToGridAct->isChecked() != enabled) {
mSnapToGridAct->setChecked(enabled);
}
}

void MainWindow::onSnappingActiveChanged(bool active)
{
if (!mSnappingAct) { return; }
QSignalBlocker blocker(mSnappingAct);
if (mSnappingAct->isChecked() != active) {
mSnappingAct->setChecked(active);
}
}

void MainWindow::checkAutoSaveTimer()
{
if (mShutdown) { return; }
Expand Down
18 changes: 18 additions & 0 deletions src/app/GUI/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "window.h"
#include "GUI/RenderWidgets/renderwidget.h"
#include "gizmos.h"
#include "gridcontroller.h"

#include "widgets/fontswidget.h"
#include "widgets/toolbar.h"
Expand Down Expand Up @@ -198,6 +199,10 @@ class MainWindow : public QMainWindow

void openWelcomeDialog();
void closeWelcomeDialog();
void openGridSettingsDialog();
void onGridSettingsChanged(const Friction::Core::GridSettings& settings);
void onGridSnapEnabledChanged(bool enabled);
void onSnappingActiveChanged(bool active);

eKeyFilter* mNumericFilter = eKeyFilter::sCreateNumberFilter(this);
eKeyFilter* mLineFilter = eKeyFilter::sCreateLineFilter(this);
Expand Down Expand Up @@ -255,6 +260,18 @@ class MainWindow : public QMainWindow
QAction *mZoomInAction;
QAction *mZoomOutAction;
QAction *mFitViewAction;
QAction *mShowGridAct;
QAction *mSnappingAct;
QAction *mSnapToGridAct;
QAction *mSnapToCanvasAct;
QAction *mSnapToBoxesAct;
QAction *mSnapToNodesAct;
QAction *mSnapToPivotsAct;
QAction *mSnapAnchorPivotAct;
QAction *mSnapAnchorBoundsAct;
QAction *mSnapAnchorNodesAct;
QAction *mGridSettingsAct;
QAction *mGridDrawOnTopAct;

QAction *mNoneQuality;
QAction *mLowQuality;
Expand Down Expand Up @@ -282,6 +299,7 @@ class MainWindow : public QMainWindow
QMenu *mEffectsMenu;
QMenu *mSceneMenu;
QMenu *mViewMenu;
QMenu *mGridMenu;
QMenu *mPanelsMenu;
QMenu *mRenderMenu;

Expand Down
128 changes: 128 additions & 0 deletions src/app/GUI/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,134 @@ void MainWindow::setupMenuBar()
});
cmdAddAction(mResetZoomAction);

mGridMenu = mViewMenu->addMenu(QIcon::fromTheme("grid"),
tr("Grid && Snapping", "MenuBar_View"));

mSnappingAct = mGridMenu->addAction(tr("Snapping"));
mSnappingAct->setCheckable(true);
mSnappingAct->setChecked(mDocument.isSnappingActive());
connect(mSnappingAct, &QAction::toggled, this, [this](bool checked) {
mDocument.setSnappingActive(checked);
});
cmdAddAction(mSnappingAct);

mGridMenu->addSeparator();

mSnapToCanvasAct = mGridMenu->addAction(tr("Snap to Canvas"));
mSnapToCanvasAct->setCheckable(true);
mSnapToCanvasAct->setChecked(mDocument.gridController().settings.snapToCanvas);
connect(mSnapToCanvasAct, &QAction::toggled, this, [this](bool checked) {
auto settings = mDocument.gridController().settings;
if (settings.snapToCanvas == checked) { return; }
settings.snapToCanvas = checked;
mDocument.setGridSettings(settings);
});
cmdAddAction(mSnapToCanvasAct);

mSnapToGridAct = mGridMenu->addAction(tr("Snap to Grid"));
mSnapToGridAct->setCheckable(true);
mSnapToGridAct->setChecked(mDocument.gridController().settings.enabled);
connect(mSnapToGridAct, &QAction::toggled, this, [this](bool checked) {
mDocument.setGridSnapEnabled(checked);
});
cmdAddAction(mSnapToGridAct);

mSnapToPivotsAct = mGridMenu->addAction(tr("Snap to Pivots"));
mSnapToPivotsAct->setCheckable(true);
mSnapToPivotsAct->setChecked(mDocument.gridController().settings.snapToPivots);
connect(mSnapToPivotsAct, &QAction::toggled, this, [this](bool checked) {
auto settings = mDocument.gridController().settings;
if (settings.snapToPivots == checked) { return; }
settings.snapToPivots = checked;
mDocument.setGridSettings(settings);
});
cmdAddAction(mSnapToPivotsAct);

mSnapToBoxesAct = mGridMenu->addAction(tr("Snap to Boxes"));
mSnapToBoxesAct->setCheckable(true);
mSnapToBoxesAct->setChecked(mDocument.gridController().settings.snapToBoxes);
connect(mSnapToBoxesAct, &QAction::toggled, this, [this](bool checked) {
auto settings = mDocument.gridController().settings;
if (settings.snapToBoxes == checked) { return; }
settings.snapToBoxes = checked;
mDocument.setGridSettings(settings);
});
cmdAddAction(mSnapToBoxesAct);

mSnapToNodesAct = mGridMenu->addAction(tr("Snap to Nodes"));
mSnapToNodesAct->setCheckable(true);
mSnapToNodesAct->setChecked(mDocument.gridController().settings.snapToNodes);
connect(mSnapToNodesAct, &QAction::toggled, this, [this](bool checked) {
auto settings = mDocument.gridController().settings;
if (settings.snapToNodes == checked) { return; }
settings.snapToNodes = checked;
mDocument.setGridSettings(settings);
});
cmdAddAction(mSnapToNodesAct);

mGridMenu->addSeparator();

mSnapAnchorPivotAct = mGridMenu->addAction(tr("Pivot anchor"));
mSnapAnchorPivotAct->setCheckable(true);
mSnapAnchorPivotAct->setChecked(mDocument.gridController().settings.snapAnchorPivot);
connect(mSnapAnchorPivotAct, &QAction::toggled, this, [this](bool checked) {
auto settings = mDocument.gridController().settings;
if (settings.snapAnchorPivot == checked) { return; }
settings.snapAnchorPivot = checked;
mDocument.setGridSettings(settings);
});
cmdAddAction(mSnapAnchorPivotAct);

mSnapAnchorBoundsAct = mGridMenu->addAction(tr("Boxes anchors"));
mSnapAnchorBoundsAct->setCheckable(true);
mSnapAnchorBoundsAct->setChecked(mDocument.gridController().settings.snapAnchorBounds);
connect(mSnapAnchorBoundsAct, &QAction::toggled, this, [this](bool checked) {
auto settings = mDocument.gridController().settings;
if (settings.snapAnchorBounds == checked) { return; }
settings.snapAnchorBounds = checked;
mDocument.setGridSettings(settings);
});
cmdAddAction(mSnapAnchorBoundsAct);

mSnapAnchorNodesAct = mGridMenu->addAction(tr("Nodes anchors"));
mSnapAnchorNodesAct->setCheckable(true);
mSnapAnchorNodesAct->setChecked(mDocument.gridController().settings.snapAnchorNodes);
connect(mSnapAnchorNodesAct, &QAction::toggled, this, [this](bool checked) {
auto settings = mDocument.gridController().settings;
if (settings.snapAnchorNodes == checked) { return; }
settings.snapAnchorNodes = checked;
mDocument.setGridSettings(settings);
});
cmdAddAction(mSnapAnchorNodesAct);

mGridMenu->addSeparator();

mShowGridAct = mGridMenu->addAction(tr("Show Grid"));
mShowGridAct->setCheckable(true);
mShowGridAct->setChecked(mDocument.gridController().settings.show);
connect(mShowGridAct, &QAction::toggled, this, [this](bool checked) {
mDocument.setGridVisible(checked);
});
cmdAddAction(mShowGridAct);

mGridDrawOnTopAct = mGridMenu->addAction(tr("Grid on top"));
mGridDrawOnTopAct->setCheckable(true);
connect(mGridDrawOnTopAct, &QAction::toggled, this, [this](bool checked) {
auto settings = mDocument.gridController().settings;
if (settings.drawOnTop == checked) { return; }
settings.drawOnTop = checked;
mDocument.setGridSettings(settings);
});
cmdAddAction(mGridDrawOnTopAct);

mGridMenu->addSeparator();

mGridSettingsAct = mGridMenu->addAction(tr("Grid Settings..."));
connect(mGridSettingsAct, &QAction::triggered, this, &MainWindow::openGridSettingsDialog);
cmdAddAction(mGridSettingsAct);

onGridSettingsChanged(mDocument.gridController().settings);

const auto filteringMenu = mViewMenu->addMenu(QIcon::fromTheme("user-desktop"),
tr("Filtering", "MenuBar_View"));

Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ include_directories(
set(
SOURCES
appsupport.cpp
gridcontroller.cpp
Boxes/nullobject.cpp
Expressions/expression.cpp
Expressions/expressionpresets.cpp
Expand Down Expand Up @@ -359,6 +360,7 @@ set(
set(
HEADERS
appsupport.h
gridcontroller.h
Boxes/nullobject.h
Expressions/expression.h
Expressions/expressionpresets.h
Expand Down
Loading