Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tool_transform_config_widget.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include <QVector3D>
9
10#include <kis_icon.h>
11#include "rotation_icons.h"
12#include "kis_canvas2.h"
13#include <KisSignalMapper.h>
15
16#include "KisMainWindow.h"
17#include "KisViewManager.h"
18#include "kis_transform_utils.h"
19#include "kis_config_notifier.h"
20#include <kstandardguiitem.h>
22
23
24template<typename T> inline T sign(T x) {
25 return x > 0 ? 1 : x == (T)0 ? 0 : -1;
26}
27
29
30
32 : QWidget(parent),
33 m_transaction(transaction),
34 m_notificationsBlocked(0),
35 m_uiSlotsBlocked(0),
36 m_configChanged(false)
37{
38 setupUi(this);
39
40 KConfigGroup group = KSharedConfig::openConfig()->group("KisToolTransform");
41 bool useInStackPreview = !group.readEntry("useOverlayPreviewStyle", false);
42 bool forceLodMode = group.readEntry("forceLodMode", true);
43
44 if (useInStackPreview && !forceLodMode) {
45 cmbPreviewMode->setCurrentIndex(0);
46 }
47 else if (useInStackPreview && forceLodMode) {
48 cmbPreviewMode->setCurrentIndex(1);
49 }
50 else {
51 cmbPreviewMode->setCurrentIndex(2);
52 }
53
54 connect(cmbPreviewMode, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPreviewChanged(int)));
55
56 flipXButton->setIcon(KisIconUtils::loadIcon("transform_icons_mirror_x"));
57 flipYButton->setIcon(KisIconUtils::loadIcon("transform_icons_mirror_y"));
58 rotateCWButton->setIcon(KisIconUtils::loadIcon("transform_icons_rotate_cw"));
59 rotateCCWButton->setIcon(KisIconUtils::loadIcon("transform_icons_rotate_ccw"));
60
61 // Granularity can only be specified in the power of 2's
62 QStringList granularityValues{"4","8","16","32"};
63 changeGranularity->addItems(granularityValues);
64 changeGranularity->setCurrentIndex(1);
65 granularityPreview->addItems(granularityValues);
66 granularityPreview->setCurrentIndex(2);
67
68 connect(changeGranularity,SIGNAL(currentTextChanged(QString)),
69 this,SLOT(slotGranularityChanged(QString)));
70 connect(granularityPreview, SIGNAL(currentTextChanged(QString)),
71 this,SLOT(slotPreviewGranularityChanged(QString)));
72
73 // Init Filter combo
74 cmbFilter->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
75 cmbFilter->setCurrent("Bicubic");
76 cmbFilter->setToolTip(i18nc("@info:tooltip",
77 "<p>Select filtering mode:\n"
78 "<ul>"
79 "<li><b>Nearest neighbor</b> for pixel art. Does not produce new color.</li>"
80 "<li><b>Bilinear</b> for areas with uniform color to avoid artifacts.</li>"
81 "<li><b>Bicubic</b> for smoother results.</li>"
82 "<li><b>Lanczos3</b> for sharp results. May produce aerials.</li>"
83 "</ul></p>"));
84 connect(cmbFilter, SIGNAL(activated(KoID)),
85 this, SLOT(slotFilterChanged(KoID)));
86
87 // Init Warp Type combo
88 cmbWarpType->insertItem(KisWarpTransformWorker::AFFINE_TRANSFORM,i18n("Default (Affine)"));
89 cmbWarpType->insertItem(KisWarpTransformWorker::RIGID_TRANSFORM,i18n("Strong (Rigid)"));
90 cmbWarpType->insertItem(KisWarpTransformWorker::SIMILITUDE_TRANSFORM,i18n("Strongest (Similitude)"));
91 cmbWarpType->setCurrentIndex(KisWarpTransformWorker::AFFINE_TRANSFORM);
92 connect(cmbWarpType, SIGNAL(currentIndexChanged(int)), this, SLOT(slotWarpTypeChanged(int)));
93
94 // Init Rotation Center buttons
95 m_handleDir[0] = QPointF(1, 0);
96 m_handleDir[1] = QPointF(1, -1);
97 m_handleDir[2] = QPointF(0, -1);
98 m_handleDir[3] = QPointF(-1, -1);
99 m_handleDir[4] = QPointF(-1, 0);
100 m_handleDir[5] = QPointF(-1, 1);
101 m_handleDir[6] = QPointF(0, 1);
102 m_handleDir[7] = QPointF(1, 1);
103 m_handleDir[8] = QPointF(0, 0); // also add the center
104
105 m_rotationCenterButtons = new QButtonGroup(0);
106 // we set the ids to match m_handleDir
107 m_rotationCenterButtons->addButton(middleRightButton, 0);
108 m_rotationCenterButtons->addButton(topRightButton, 1);
109 m_rotationCenterButtons->addButton(middleTopButton, 2);
110 m_rotationCenterButtons->addButton(topLeftButton, 3);
111 m_rotationCenterButtons->addButton(middleLeftButton, 4);
112 m_rotationCenterButtons->addButton(bottomLeftButton, 5);
113 m_rotationCenterButtons->addButton(middleBottomButton, 6);
114 m_rotationCenterButtons->addButton(bottomRightButton, 7);
115 m_rotationCenterButtons->addButton(centerButton, 8);
116
117 QToolButton *nothingSelected = new QToolButton(0);
118 nothingSelected->setCheckable(true);
119 nothingSelected->setAutoExclusive(true);
120 nothingSelected->hide(); // a convenient button for when no button is checked in the group
121 m_rotationCenterButtons->addButton(nothingSelected, 9);
122
123
124 // initialize values for free transform sliders
125 shearXBox->setSuffix(QStringLiteral("%"));
126 shearYBox->setSuffix(QStringLiteral("%"));
127 shearXBox->setRange(-500, 500, 2);
128 shearYBox->setRange(-500, 500, 2);
129 shearXBox->setSingleStep(1);
130 shearYBox->setSingleStep(1);
131 shearXBox->setValue(0.0);
132 shearYBox->setValue(0.0);
133
134
135 translateXBox->setSuffix(i18n(" px"));
136 translateYBox->setSuffix(i18n(" px"));
137 translateXBox->setRange(-10000, 10000);
138 translateYBox->setRange(-10000, 10000);
139
140
141 scaleXBox->setRange(-10000, 10000);
142 scaleYBox->setRange(-10000, 10000);
143 scaleXBox->setValue(100.0);
144 scaleYBox->setValue(100.0);
145 KisSpinBoxI18nHelper::setText(scaleXBox, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
146 KisSpinBoxI18nHelper::setText(scaleYBox, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
147
148 m_scaleRatio = 1.0;
149
150
151 aXBox->setIncreasingDirection(KisAngleGauge::IncreasingDirection_Clockwise);
152 aYBox->setIncreasingDirection(KisAngleGauge::IncreasingDirection_Clockwise);
153 aZBox->setIncreasingDirection(KisAngleGauge::IncreasingDirection_Clockwise);
154 aXBox->setFlipOptionsMode(KisAngleSelector::FlipOptionsMode_MenuButton);
155 aYBox->setFlipOptionsMode(KisAngleSelector::FlipOptionsMode_MenuButton);
156 aZBox->setFlipOptionsMode(KisAngleSelector::FlipOptionsMode_MenuButton);
157
158 cameraHeightBox->setRange(1, 20000, 2);
159
160 connect(m_rotationCenterButtons, SIGNAL(idPressed(int)), this, SLOT(slotRotationCenterChanged(int)));
161 connect(btnTransformAroundPivotPoint, SIGNAL(clicked(bool)), this, SLOT(slotTransformAroundRotationCenter(bool)));
162
163 // Init Free Transform Values
164 connect(scaleXBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetScaleX(int)));
165 connect(scaleYBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetScaleY(int)));
166 connect(shearXBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetShearX(qreal)));
167 connect(shearYBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetShearY(qreal)));
168 connect(translateXBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetTranslateX(int)));
169 connect(translateYBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetTranslateY(int)));
170 connect(aXBox, SIGNAL(angleChanged(qreal)), this, SLOT(slotSetAX(qreal)));
171 connect(aYBox, SIGNAL(angleChanged(qreal)), this, SLOT(slotSetAY(qreal)));
172 connect(aZBox, SIGNAL(angleChanged(qreal)), this, SLOT(slotSetAZ(qreal)));
173 connect(cameraHeightBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetCameraHeight(qreal)));
174 connect(aspectButton, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slotSetKeepAspectRatio(bool)));
175 connect(flipXButton, SIGNAL(clicked(bool)), this, SLOT(slotFlipX()));
176 connect(flipYButton, SIGNAL(clicked(bool)), this, SLOT(slotFlipY()));
177 connect(rotateCWButton, SIGNAL(clicked(bool)), this, SLOT(slotRotateCW()));
178 connect(rotateCCWButton, SIGNAL(clicked(bool)), this, SLOT(slotRotateCCW()));
179
180 // toggle visibility of different free buttons
181 connect(freeMoveRadioButton, SIGNAL(clicked(bool)), SLOT(slotTransformAreaVisible(bool)));
182 connect(freeRotationRadioButton, SIGNAL(clicked(bool)), SLOT(slotTransformAreaVisible(bool)));
183 connect(freeScaleRadioButton, SIGNAL(clicked(bool)), SLOT(slotTransformAreaVisible(bool)));
184 connect(freeShearRadioButton, SIGNAL(clicked(bool)), SLOT(slotTransformAreaVisible(bool)));
185
186 // only first group for free transform
187 rotationGroup->hide();
188 moveGroup->show();
189 scaleGroup->hide();
190 shearGroup->hide();
191
192
193
194 // Init Warp Transform Values
195 alphaBox->setSingleStep(0.1);
196 alphaBox->setRange(0, 10, 1);
197
198 connect(alphaBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetWarpAlpha(qreal)));
199 connect(densityBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetWarpDensity(int)));
200
201 connect(defaultRadioButton, SIGNAL(clicked(bool)), this, SLOT(slotWarpDefaultPointsButtonClicked(bool)));
202 connect(customRadioButton, SIGNAL(clicked(bool)), this, SLOT(slotWarpCustomPointsButtonClicked(bool)));
203 connect(lockUnlockPointsButton, SIGNAL(clicked()), this, SLOT(slotWarpLockPointsButtonClicked()));
204 connect(resetPointsButton, SIGNAL(clicked()), this, SLOT(slotWarpResetPointsButtonClicked()));
205
206 // Init Cage Transform Values
207 cageTransformButtonGroup->setId(cageAddEditRadio, 0); // we need to set manually since Qt Designer generates negative by default
208 cageTransformButtonGroup->setId(cageDeformRadio, 1);
209 connect(cageTransformButtonGroup, SIGNAL(idClicked(int)), this, SLOT(slotCageOptionsChanged(int)));
210
211 // Init Liquify Transform Values
212 liquifySizeSlider->setRange(KisLiquifyProperties::minSize(),
214 liquifySizeSlider->setExponentRatio(3);
215 liquifySizeSlider->setValue(60.0);
216 connect(liquifySizeSlider, SIGNAL(valueChanged(qreal)), this, SLOT(liquifySizeChanged(qreal)));
217 connect(liquifySizeSlider, SIGNAL(editingFinished()), SLOT(notifyEditingFinished()));
218 liquifySizeSlider->setToolTip(i18nc("@info:tooltip", "Size of the deformation brush"));
219
220 liquifyAmountSlider->setRange(0.0, 1.0, 2);
221 liquifyAmountSlider->setSingleStep(0.01);
222 liquifyAmountSlider->setValue(0.05);
223 connect(liquifyAmountSlider, SIGNAL(valueChanged(qreal)), this, SLOT(liquifyAmountChanged(qreal)));
224 connect(liquifyAmountSlider, SIGNAL(editingFinished()), SLOT(notifyEditingFinished()));
225 liquifyAmountSlider->setToolTip(i18nc("@info:tooltip", "Amount of the deformation you get"));
226
227 liquifyFlowSlider->setRange(0.0, 1.0, 2);
228 liquifyFlowSlider->setSingleStep(0.01);
229 liquifyFlowSlider->setValue(1.0);
230 connect(liquifyFlowSlider, SIGNAL(valueChanged(qreal)), this, SLOT(liquifyFlowChanged(qreal)));
231 connect(liquifyFlowSlider, SIGNAL(editingFinished()), SLOT(notifyEditingFinished()));
232 liquifyFlowSlider->setToolTip(i18nc("@info:tooltip", "When in non-buildup mode, shows how fast the deformation limit is reached."));
233
234 buildupModeComboBox->setCurrentIndex(0); // set to build-up mode by default
235 connect(buildupModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(liquifyBuildUpChanged(int)));
236 connect(buildupModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(notifyEditingFinished()));
237 buildupModeComboBox->setToolTip("<p>" + i18nc("@info:tooltip", "Switch between Build Up and Wash mode of painting. Build Up mode adds deformations one on top of the other without any limits. Wash mode gradually deforms the piece to the selected deformation level.") + "</p>");
238
239 liquifySpacingSlider->setRange(0.0, 3.0, 2);
240 liquifySpacingSlider->setExponentRatio(3);
241 liquifySpacingSlider->setSingleStep(0.01);
242 liquifySpacingSlider->setValue(0.2);
243 connect(liquifySpacingSlider, SIGNAL(valueChanged(qreal)), this, SLOT(liquifySpacingChanged(qreal)));
244 connect(liquifySpacingSlider, SIGNAL(editingFinished()), SLOT(notifyEditingFinished()));
245 liquifySpacingSlider->setToolTip(i18nc("@info:tooltip", "Space between two sequential applications of the deformation"));
246
247 liquifySizePressureBox->setChecked(true);
248 connect(liquifySizePressureBox, SIGNAL(toggled(bool)), this, SLOT(liquifySizePressureChanged(bool)));
249 connect(liquifySizePressureBox, SIGNAL(toggled(bool)), this, SLOT(notifyEditingFinished()));
250 liquifySizePressureBox->setToolTip(i18nc("@info:tooltip", "Scale <b>Size</b> value according to current stylus pressure"));
251
252 liquifyAmountPressureBox->setChecked(true);
253 connect(liquifyAmountPressureBox, SIGNAL(toggled(bool)), this, SLOT(liquifyAmountPressureChanged(bool)));
254 connect(liquifyAmountPressureBox, SIGNAL(toggled(bool)), this, SLOT(notifyEditingFinished()));
255 liquifyAmountPressureBox->setToolTip(i18nc("@info:tooltip", "Scale <b>Amount</b> value according to current stylus pressure"));
256
257 liquifyReverseDirectionChk->setChecked(false);
258 connect(liquifyReverseDirectionChk, SIGNAL(toggled(bool)), this, SLOT(liquifyReverseDirectionChanged(bool)));
259 connect(liquifyReverseDirectionChk, SIGNAL(toggled(bool)), this, SLOT(notifyEditingFinished()));
260 liquifyReverseDirectionChk->setToolTip(i18nc("@info:tooltip", "Reverse direction of the current deformation tool"));
261
262 KisSignalMapper *liquifyModeMapper = new KisSignalMapper(this);
263 connect(liquifyMove, SIGNAL(clicked(bool)), liquifyModeMapper, SLOT(map()));
264 connect(liquifyScale, SIGNAL(clicked(bool)), liquifyModeMapper, SLOT(map()));
265 connect(liquifyRotate, SIGNAL(clicked(bool)), liquifyModeMapper, SLOT(map()));
266 connect(liquifyOffset, SIGNAL(clicked(bool)), liquifyModeMapper, SLOT(map()));
267 connect(liquifyUndo, SIGNAL(clicked(bool)), liquifyModeMapper, SLOT(map()));
268 connect(liquifyRestoreShape, SIGNAL(clicked(bool)), liquifyModeMapper, SLOT(map()));
269 liquifyModeMapper->setMapping(liquifyMove, (int)KisLiquifyProperties::MOVE);
270 liquifyModeMapper->setMapping(liquifyScale, (int)KisLiquifyProperties::SCALE);
271 liquifyModeMapper->setMapping(liquifyRotate, (int)KisLiquifyProperties::ROTATE);
272 liquifyModeMapper->setMapping(liquifyOffset, (int)KisLiquifyProperties::OFFSET);
273 liquifyModeMapper->setMapping(liquifyUndo, (int)KisLiquifyProperties::UNDO);
274 liquifyModeMapper->setMapping(liquifyRestoreShape, (int)KisLiquifyProperties::RESTORE_SHAPE);
275 connect(liquifyModeMapper, SIGNAL(mapped(int)), SLOT(slotLiquifyModeChanged(int)));
276 connect(liquifyModeMapper, SIGNAL(mapped(int)), SLOT(notifyEditingFinished()));
277
278 liquifyMove->setToolTip(i18nc("@info:tooltip", "Move: drag the image along the brush stroke"));
279 liquifyScale->setToolTip(i18nc("@info:tooltip", "Scale: grow/shrink image under cursor"));
280 liquifyRotate->setToolTip(i18nc("@info:tooltip", "Rotate: twirl image under cursor"));
281 liquifyOffset->setToolTip(i18nc("@info:tooltip", "Offset: shift the image to the right of the stroke direction"));
282 liquifyUndo->setToolTip(i18nc("@info:tooltip", "Undo: erase actions of other tools"));
283 liquifyRestoreShape->setToolTip(i18nc("@info:tooltip",
284 "Restore Shape: reduce local liquify stretching and bunching while keeping the affected area centered"));
285
286 m_restoreShapeRotationButtons = new QButtonGroup(this);
287 m_restoreShapeRotationButtons->addButton(liquifyRestoreShapeRotationOriginal, 0);
288 m_restoreShapeRotationButtons->addButton(liquifyRestoreShapeRotationPreserve, 1);
289 connect(m_restoreShapeRotationButtons, SIGNAL(idClicked(int)), this, SLOT(liquifyPreserveShapeRotationChanged(int)));
290 connect(m_restoreShapeRotationButtons, SIGNAL(idClicked(int)), this, SLOT(notifyEditingFinished()));
291
292 m_restoreShapeScaleButtons = new QButtonGroup(this);
293 m_restoreShapeScaleButtons->addButton(liquifyRestoreShapeScaleOriginal, 0);
294 m_restoreShapeScaleButtons->addButton(liquifyRestoreShapeScalePreserve, 1);
295 connect(m_restoreShapeScaleButtons, SIGNAL(idClicked(int)), this, SLOT(liquifyPreserveShapeScaleChanged(int)));
296 connect(m_restoreShapeScaleButtons, SIGNAL(idClicked(int)), this, SLOT(notifyEditingFinished()));
297
298 m_restoreShapeStretchButtons = new QButtonGroup(this);
299 m_restoreShapeStretchButtons->addButton(liquifyRestoreShapeStretchOriginal, 0);
300 m_restoreShapeStretchButtons->addButton(liquifyRestoreShapeStretchPreserve, 1);
301 connect(m_restoreShapeStretchButtons, SIGNAL(idClicked(int)), this, SLOT(liquifyPreserveShapeStretchChanged(int)));
302 connect(m_restoreShapeStretchButtons, SIGNAL(idClicked(int)), this, SLOT(notifyEditingFinished()));
303
304 liquifyRestoreShapeRotationOriginal->setToolTip(i18nc("@info:tooltip", "Rotate the affected area back toward its original orientation"));
305 liquifyRestoreShapeRotationPreserve->setToolTip(i18nc("@info:tooltip", "Keep the current rotation of the affected area"));
306 liquifyRestoreShapeScaleOriginal->setToolTip(i18nc("@info:tooltip", "Scale the affected area back toward its original size"));
307 liquifyRestoreShapeScalePreserve->setToolTip(i18nc("@info:tooltip", "Keep the current overall scale of the affected area"));
308 liquifyRestoreShapeStretchOriginal->setToolTip(i18nc("@info:tooltip", "Remove simple stretch or squash from the affected area"));
309 liquifyRestoreShapeStretchPreserve->setToolTip(i18nc("@info:tooltip", "Keep simple stretch or squash while removing shear-like distortion"));
310
311 const auto setRestoreShapeButtonStyle = [] (QToolButton *button, bool isLeftButton) {
312 button->setStyleSheet(QString::fromLatin1(
313 "QToolButton {"
314 " border: 1px solid palette(mid);"
315 " background-color: palette(button);"
316 " color: palette(button-text);"
317 " padding: 4px 10px;"
318 " %1"
319 "}"
320 "QToolButton:hover {"
321 " background-color: palette(light);"
322 "}"
323 "QToolButton:pressed {"
324 " background-color: palette(midlight);"
325 "}"
326 "QToolButton:checked {"
327 " background-color: palette(highlight);"
328 " color: palette(highlighted-text);"
329 " border-color: palette(highlight);"
330 "}"
331 "QToolButton:checked:hover {"
332 " background-color: palette(highlight);"
333 " color: palette(highlighted-text);"
334 "}")
335 .arg(isLeftButton ?
336 QLatin1String("border-top-right-radius: 0px; border-bottom-right-radius: 0px;") :
337 QLatin1String("border-top-left-radius: 0px; border-bottom-left-radius: 0px;")));
338 };
339
340 setRestoreShapeButtonStyle(liquifyRestoreShapeRotationOriginal, true);
341 setRestoreShapeButtonStyle(liquifyRestoreShapeRotationPreserve, false);
342 setRestoreShapeButtonStyle(liquifyRestoreShapeScaleOriginal, true);
343 setRestoreShapeButtonStyle(liquifyRestoreShapeScalePreserve, false);
344 setRestoreShapeButtonStyle(liquifyRestoreShapeStretchOriginal, true);
345 setRestoreShapeButtonStyle(liquifyRestoreShapeStretchPreserve, false);
346
347 // Connect all edit boxes to the Editing Finished signal
348 connect(densityBox, SIGNAL(editingFinished()), this, SLOT(notifyEditingFinished()));
349
350
351
352 // Connect other widget (not having editingFinished signal) to
353 // the same slot. From Qt 4.6 onwards the sequence of the signal
354 // delivery is definite.
355 connect(cmbFilter, SIGNAL(activated(KoID)), this, SLOT(notifyEditingFinished()));
356 connect(cmbWarpType, SIGNAL(currentIndexChanged(int)), this, SLOT(notifyEditingFinished()));
357 connect(m_rotationCenterButtons, SIGNAL(idPressed(int)), this, SLOT(notifyEditingFinished()));
358 connect(aspectButton, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(notifyEditingFinished()));
359
360 connect(lockUnlockPointsButton, SIGNAL(clicked()), this, SLOT(notifyEditingFinished()));
361 connect(resetPointsButton, SIGNAL(clicked()), this, SLOT(notifyEditingFinished()));
362
363 connect(defaultRadioButton, SIGNAL(clicked(bool)), this, SLOT(notifyEditingFinished()));
364 connect(customRadioButton, SIGNAL(clicked(bool)), this, SLOT(notifyEditingFinished()));
365
366 // Liquify
367 //
368 // liquify brush options do not affect the image directly and are not
369 // saved to undo, so we don't Q_EMIT notifyEditingFinished() for them
370
371 // Connect Apply/Reset buttons
372 connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(slotButtonBoxClicked(QAbstractButton*)));
373
374 // Mesh. First set up, then connect.
375 intNumRows->setRange(1, 999);
376 intNumColumns->setRange(1, 999);
377
378 connect(chkShowControlPoints, SIGNAL(toggled(bool)), this, SLOT(slotMeshShowHandlesChanged()));
379 connect(chkSymmetricalHandles, SIGNAL(toggled(bool)), this, SLOT(slotMeshSymmetricalHandlesChanged()));
380 connect(chkScaleHandles, SIGNAL(toggled(bool)), this, SLOT(slotMeshScaleHandlesChanged()));
381 connect(intNumColumns, SIGNAL(valueChanged(int)), this, SLOT(slotMeshSizeChanged()));
382 connect(intNumRows, SIGNAL(valueChanged(int)), this, SLOT(slotMeshSizeChanged()));
383 connect(intNumColumns, SIGNAL(editingFinished()), this, SLOT(notifyEditingFinished()));
384 connect(intNumRows, SIGNAL(editingFinished()), this, SLOT(notifyEditingFinished()));
385
386 // Mode switch buttons
387 connect(freeTransformButton, SIGNAL(clicked(bool)), this, SLOT(slotSetFreeTransformModeButtonClicked(bool)));
388 connect(warpButton, SIGNAL(clicked(bool)), this, SLOT(slotSetWarpModeButtonClicked(bool)));
389 connect(cageButton, SIGNAL(clicked(bool)), this, SLOT(slotSetCageModeButtonClicked(bool)));
390 connect(perspectiveTransformButton, SIGNAL(clicked(bool)), this, SLOT(slotSetPerspectiveModeButtonClicked(bool)));
391 connect(liquifyButton, SIGNAL(clicked(bool)), this, SLOT(slotSetLiquifyModeButtonClicked(bool)));
392 connect(meshButton, SIGNAL(clicked(bool)), this, SLOT(slotSetMeshModeButtonClicked(bool)));
393
394
395 tooBigLabelWidget->hide();
396
397 connect(canvas->viewManager()->mainWindow(), SIGNAL(themeChanged()), SLOT(slotUpdateIcons()), Qt::UniqueConnection);
399
400 KGuiItem::assign(buttonBox->button(QDialogButtonBox::Apply), KStandardGuiItem::apply());
401 KGuiItem::assign(buttonBox->button(QDialogButtonBox::Reset), KStandardGuiItem::reset());
402}
403
405{
406 freeTransformButton->setIcon(KisIconUtils::loadIcon("transform_icons_main"));
407 warpButton->setIcon(KisIconUtils::loadIcon("transform_icons_warp"));
408 cageButton->setIcon(KisIconUtils::loadIcon("transform_icons_cage"));
409 perspectiveTransformButton->setIcon(KisIconUtils::loadIcon("transform_icons_perspective"));
410 liquifyButton->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_main"));
411 meshButton->setIcon(KisIconUtils::loadIcon("transform_icons_mesh"));
412
413 liquifyMove->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_move"));
414 liquifyScale->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_resize"));
415 liquifyRotate->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_rotate"));
416 liquifyOffset->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_offset"));
417 liquifyUndo->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_erase"));
418 liquifyRestoreShape->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_relax"));
419
420
421
422 middleRightButton->setIcon(KisIconUtils::loadIcon("arrow-right"));
423 topRightButton->setIcon(KisIconUtils::loadIcon("arrow-topright"));
424 middleTopButton->setIcon(KisIconUtils::loadIcon("arrow-up"));
425 topLeftButton->setIcon(KisIconUtils::loadIcon("arrow-topleft"));
426 middleLeftButton->setIcon(KisIconUtils::loadIcon("arrow-left"));
427 bottomLeftButton->setIcon(KisIconUtils::loadIcon("arrow-downleft"));
428 middleBottomButton->setIcon(KisIconUtils::loadIcon("arrow-down"));
429 bottomRightButton->setIcon(KisIconUtils::loadIcon("arrow-downright"));
430
431 btnTransformAroundPivotPoint->setIcon(KisIconUtils::loadIcon("pivot-point"));
432
433
434 // pressure icons
435 liquifySizePressureBox->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure"));
436 liquifyAmountPressureBox->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure"));
437}
438
440{
441 blockUiSlots();
442
444 KisLiquifyProperties *props =
445 config->liquifyProperties();
446
447 const bool useWashMode = props->useWashMode();
448
449 liquifySizeSlider->setValue(props->size());
450 liquifyAmountSlider->setValue(props->amount());
451 liquifyFlowSlider->setValue(props->flow());
452 buildupModeComboBox->setCurrentIndex(useWashMode);
453
454 liquifySpacingSlider->setValue(props->spacing());
455 liquifySizePressureBox->setChecked(props->sizeHasPressure());
456 liquifyAmountPressureBox->setChecked(props->amountHasPressure());
457 liquifyReverseDirectionChk->setChecked(props->reverseDirection());
458 liquifyRestoreShapeRotationOriginal->setChecked(!props->preserveShapeRotation());
459 liquifyRestoreShapeRotationPreserve->setChecked(props->preserveShapeRotation());
460 liquifyRestoreShapeScaleOriginal->setChecked(!props->preserveShapeScale());
461 liquifyRestoreShapeScalePreserve->setChecked(props->preserveShapeScale());
462 liquifyRestoreShapeStretchOriginal->setChecked(!props->preserveShapeStretch());
463 liquifyRestoreShapeStretchPreserve->setChecked(props->preserveShapeStretch());
464
465
467 static_cast<KisLiquifyProperties::LiquifyMode>(props->mode());
468
469 bool canInverseDirection = KisLiquifyProperties::supportsReverseDirection(mode);
470 bool canUseWashMode = KisLiquifyProperties::supportsWashMode(mode);
471 bool isRestoreShapeMode = mode == KisLiquifyProperties::RESTORE_SHAPE;
472
473 liquifyReverseDirectionChk->setEnabled(canInverseDirection);
474 liquifyFlowSlider->setEnabled(canUseWashMode && useWashMode);
475 buildupModeComboBox->setEnabled(canUseWashMode);
476 lblLiquifyShapeRotation->setVisible(isRestoreShapeMode);
477 liquifyRestoreShapeRotationOriginal->setVisible(isRestoreShapeMode);
478 liquifyRestoreShapeRotationPreserve->setVisible(isRestoreShapeMode);
479 lblLiquifyShapeScale->setVisible(isRestoreShapeMode);
480 liquifyRestoreShapeScaleOriginal->setVisible(isRestoreShapeMode);
481 liquifyRestoreShapeScalePreserve->setVisible(isRestoreShapeMode);
482 lblLiquifyShapeStretch->setVisible(isRestoreShapeMode);
483 liquifyRestoreShapeStretchOriginal->setVisible(isRestoreShapeMode);
484 liquifyRestoreShapeStretchPreserve->setVisible(isRestoreShapeMode);
485
486 const qreal maxAmount = canUseWashMode ? 5.0 : 1.0;
487 liquifyAmountSlider->setRange(0.0, maxAmount, 2);
488
490}
491
493{
494 if (m_uiSlotsBlocked) return;
495
497
498 KisLiquifyProperties *props =
499 config->liquifyProperties();
500
503
504 if (mode == props->mode()) return;
505
506 props->setMode(mode);
507 props->loadMode();
508
510
511 notifyConfigChanged(false);
512}
513
515{
516 if (m_uiSlotsBlocked) return;
517
519 KisLiquifyProperties *props =
520 config->liquifyProperties();
521
522 props->setSize(value);
523 notifyConfigChanged(false);
524}
525
527{
528 if (m_uiSlotsBlocked) return;
529
531 KisLiquifyProperties *props =
532 config->liquifyProperties();
533
534 props->setAmount(value);
535 notifyConfigChanged(false);
536}
537
539{
540 if (m_uiSlotsBlocked) return;
541
543 KisLiquifyProperties *props =
544 config->liquifyProperties();
545
546 props->setFlow(value);
547 notifyConfigChanged(false);
548}
549
551{
552 if (m_uiSlotsBlocked) return;
553
555 KisLiquifyProperties *props =
556 config->liquifyProperties();
557
558 props->setUseWashMode(value); // 0 == build up mode / 1 == wash mode
559
560 notifyConfigChanged(false);
561
562 // we need to enable/disable flow slider
564}
565
567{
568 if (m_uiSlotsBlocked) return;
569
571 KisLiquifyProperties *props =
572 config->liquifyProperties();
573
574 props->setSpacing(value);
575 notifyConfigChanged(false);
576}
577
589
601
613
625
637
649
651{
652 blockUiSlots();
653
654 if (config.mode() == ToolTransformArgs::FREE_TRANSFORM ||
656
657 quickTransformGroup->setEnabled(config.mode() == ToolTransformArgs::FREE_TRANSFORM);
658
659 stackedWidget->setCurrentIndex(0);
660
661 bool freeTransformIsActive = config.mode() == ToolTransformArgs::FREE_TRANSFORM;
662
663 if (freeTransformIsActive)
664 {
665 freeTransformButton->setChecked(true);
666 }
667 else
668 {
669 perspectiveTransformButton->setChecked(true);
670 }
671
672 aXBox->setEnabled(freeTransformIsActive);
673 aYBox->setEnabled(freeTransformIsActive);
674 aZBox->setEnabled(freeTransformIsActive);
675 cameraHeightBox->setEnabled(freeTransformIsActive);
676 freeRotationRadioButton->setEnabled(freeTransformIsActive);
677
678 scaleXBox->setValue(config.scaleX() * 100.);
679 scaleYBox->setValue(config.scaleY() * 100.);
680 shearXBox->setValue(config.shearX() * 100.);
681 shearYBox->setValue(config.shearY() * 100.);
682
683 const QPointF anchorPoint = config.originalCenter() + config.rotationCenterOffset();
684 const KisTransformUtils::MatricesPack m(config);
685 const QPointF anchorPointView = m.finalTransform().map(anchorPoint);
686
687 translateXBox->setValue(anchorPointView.x());
688 translateYBox->setValue(anchorPointView.y());
689
690 aXBox->setAngle(normalizeAngleDegrees(kisRadiansToDegrees(config.aX())));
691 aYBox->setAngle(normalizeAngleDegrees(kisRadiansToDegrees(config.aY())));
692 aZBox->setAngle(normalizeAngleDegrees(kisRadiansToDegrees(config.aZ())));
693 cameraHeightBox->setValue(config.cameraPos().z());
694 aspectButton->setKeepAspectRatio(config.keepAspectRatio());
695 cmbFilter->setCurrent(config.filterId());
696
698 pt.rx() /= m_transaction->originalHalfWidth();
699 pt.ry() /= m_transaction->originalHalfHeight();
700
701 for (int i = 0; i < 9; i++) {
702 if (qFuzzyCompare(m_handleDir[i].x(), pt.x()) &&
703 qFuzzyCompare(m_handleDir[i].y(), pt.y())) {
704
705 m_rotationCenterButtons->button(i)->setChecked(true);
706 break;
707 }
708 }
709
710 btnTransformAroundPivotPoint->setChecked(config.transformAroundRotationCenter());
711
712 } else if (config.mode() == ToolTransformArgs::WARP) {
713
714 stackedWidget->setCurrentIndex(1);
715 warpButton->setChecked(true);
716
717 if (config.defaultPoints()) {
718 densityBox->setValue(std::sqrt(config.numPoints()));
719 }
720
721 cmbWarpType->setCurrentIndex((int)config.warpType());
722 defaultRadioButton->setChecked(config.defaultPoints());
723 customRadioButton->setChecked(!config.defaultPoints());
724 densityBox->setEnabled(config.defaultPoints());
725 customWarpWidget->setEnabled(!config.defaultPoints());
726
728
729 } else if (config.mode() == ToolTransformArgs::CAGE) {
730
731 // default UI options
733
734 // we need at least 3 point before we can start actively deforming
735 if (config.origPoints().size() >= 3)
736 {
737 cageTransformDirections->setText(i18n("Switch between editing and deforming cage"));
738 cageAddEditRadio->setVisible(true);
739 cageDeformRadio->setVisible(true);
740
741 // update to correct radio button
742 if (config.isEditingTransformPoints())
743 cageAddEditRadio->setChecked(true);
744 else
745 cageDeformRadio->setChecked(true);
746
747 changeGranularity->setCurrentIndex(log2(config.pixelPrecision()) - 2);
748 granularityPreview->setCurrentIndex(log2(config.previewPixelPrecision()) - 2);
749
750 }
751
752 } else if (config.mode() == ToolTransformArgs::LIQUIFY) {
753
754 stackedWidget->setCurrentIndex(3);
755 liquifyButton->setChecked(true);
756
757 const KisLiquifyProperties *props =
758 config.liquifyProperties();
759
760 switch (props->mode()) {
762 liquifyMove->setChecked(true);
763 break;
765 liquifyScale->setChecked(true);
766 break;
768 liquifyRotate->setChecked(true);
769 break;
771 liquifyOffset->setChecked(true);
772 break;
774 liquifyUndo->setChecked(true);
775 break;
777 liquifyRestoreShape->setChecked(true);
778 break;
780 qFatal("Unsupported mode");
781 }
782
784 } else if (config.mode() == ToolTransformArgs::MESH) {
785 stackedWidget->setCurrentIndex(4);
786 intNumColumns->setValue(config.meshTransform()->size().width() - 1);
787 intNumRows->setValue(config.meshTransform()->size().height() - 1);
788 chkShowControlPoints->setChecked(config.meshShowHandles());
789 chkSymmetricalHandles->setChecked(config.meshSymmetricalHandles());
790 chkScaleHandles->setChecked(config.meshScaleHandles());
791 }
792
794}
795
797{
799
800 if (config->isEditingTransformPoints()) {
801 lockUnlockPointsButton->setText(i18n("Lock Points"));
802 } else {
803 lockUnlockPointsButton->setText(i18n("Unlock Points"));
804 }
805}
806
808{
809 QAbstractButton *applyButton = buttonBox->button(QDialogButtonBox::Apply);
810 QAbstractButton *resetButton = buttonBox->button(QDialogButtonBox::Reset);
811
812 Q_ASSERT(applyButton);
813 Q_ASSERT(resetButton);
814
815 applyButton->setDisabled(disabled);
816 resetButton->setDisabled(disabled);
817}
818
820{
821 int checkedId = m_rotationCenterButtons->checkedId();
822
823 if (checkedId >= 0 && checkedId <= 8) {
824 // uncheck the current checked button
825 m_rotationCenterButtons->button(9)->setChecked(true);
826 }
827}
828
830{
831 tooBigLabelWidget->setVisible(value);
832}
833
838
843
844void KisToolTransformConfigWidget::notifyConfigChanged(bool needsPreviewRecalculation)
845{
847 Q_EMIT sigConfigChanged(needsPreviewRecalculation);
848 }
849 m_configChanged = true;
850}
851
856
861
869
870
872{
873 // reset tool states since we are done (probably can encapsulate this later)
875 if (config->mode() == ToolTransformArgs::CAGE)
876 {
877 cageAddEditRadio->setVisible(false);
878 cageAddEditRadio->setChecked(true);
879 cageDeformRadio->setVisible(false);
880 cageTransformDirections->setText(i18n("Create 3 points on the canvas to begin"));
881
882 // ensure we are on the right options view
883 stackedWidget->setCurrentIndex(2);
884 }
885
886
887
888}
889
891{
892 QAbstractButton *applyButton = buttonBox->button(QDialogButtonBox::Apply);
893 QAbstractButton *resetButton = buttonBox->button(QDialogButtonBox::Reset);
894
896
897 if (button == applyButton) {
898 Q_EMIT sigApplyTransform();
899 }
900 else if (button == resetButton) {
901 Q_EMIT sigCancelTransform();
902 }
903
904}
905
907{
908 if (!value) return;
909
910 lblTransformType->setText(meshButton->toolTip());
911
913}
914
916{
917 if (!value) return;
918
919 lblTransformType->setText(freeTransformButton->toolTip());
920
922}
923
925{
926 if (!value) return;
927
928 lblTransformType->setText(warpButton->toolTip());
929
931}
932
934{
935 if (!value) return;
936
937 lblTransformType->setText(cageButton->toolTip());
938
940}
941
943{
944 if (!value) return;
945
946 lblTransformType->setText(liquifyButton->toolTip());
947
949}
950
952{
953 if (!value) return;
954
955 lblTransformType->setText(perspectiveTransformButton->toolTip());
956
958}
959
961{
963 config->setFilterId(filterId.id());
965}
966
968{
969 if (m_uiSlotsBlocked) return;
970
971 if (index >= 0 && index <= 8) {
973
974 double i = m_handleDir[index].x();
975 double j = m_handleDir[index].y();
976
979
981 updateConfig(*config);
982 }
983}
984
994
996{
997 if (m_uiSlotsBlocked) return;
998
1000
1001 {
1003 config->setScaleX(value / 100.);
1004 }
1005
1006 if (config->keepAspectRatio()) {
1007
1009 int calculatedValue = int( value/ m_scaleRatio );
1010
1011 scaleYBox->blockSignals(true);
1012 scaleYBox->setValue(calculatedValue);
1013 {
1015 config->setScaleY(calculatedValue / 100.);
1016 }
1017 scaleYBox->blockSignals(false);
1018
1020 }
1021
1024}
1025
1027{
1028 if (m_uiSlotsBlocked) return;
1029
1031
1032 {
1034 config->setScaleY(value / 100.);
1035 }
1036
1037 if (config->keepAspectRatio()) {
1039 int calculatedValue = int(m_scaleRatio * value);
1040 scaleXBox->blockSignals(true);
1041 scaleXBox->setValue(calculatedValue);
1042 {
1044 config->setScaleX(calculatedValue / 100.);
1045 }
1046 scaleXBox->blockSignals(false);
1048 }
1049
1052}
1053
1055{
1056 if (m_uiSlotsBlocked) return;
1057
1059
1060 {
1062 config->setShearX((double)value / 100.);
1063 }
1064
1067}
1068
1070{
1071 if (m_uiSlotsBlocked) return;
1072
1074
1075 {
1077 config->setShearY((double)value / 100.);
1078 }
1079
1080
1083}
1084
1086{
1087 if (m_uiSlotsBlocked) return;
1088
1090
1091 const QPointF anchorPoint = config->originalCenter() + config->rotationCenterOffset();
1092 const KisTransformUtils::MatricesPack m(*config);
1093
1094 const QPointF anchorPointView = m.finalTransform().map(anchorPoint);
1095 const QPointF newAnchorPointView(value, anchorPointView.y());
1096 config->setTransformedCenter(config->transformedCenter() + newAnchorPointView - anchorPointView);
1097 translateXBox->setValue(value);
1099}
1100
1102{
1103 if (m_uiSlotsBlocked) return;
1104
1106
1107 const QPointF anchorPoint = config->originalCenter() + config->rotationCenterOffset();
1108 const KisTransformUtils::MatricesPack m(*config);
1109
1110 const QPointF anchorPointView = m.finalTransform().map(anchorPoint);
1111 const QPointF newAnchorPointView(anchorPointView.x(), value);
1112 config->setTransformedCenter(config->transformedCenter() + newAnchorPointView - anchorPointView);
1113 translateYBox->setValue(value);
1115}
1116
1129
1131{
1132 if (m_uiSlotsBlocked) return;
1133
1135
1136 {
1139 }
1140
1143}
1144
1146{
1147 if (m_uiSlotsBlocked) return;
1148
1150
1151 {
1154 }
1155
1158}
1159
1161{
1162 if (m_uiSlotsBlocked) return;
1163
1165 config->setCameraPos(QVector3D(0,0,value));
1166
1169}
1170
1172{
1174
1175 {
1177 config->setScaleX(config->scaleX() * -1);
1178 }
1179
1182}
1183
1185{
1187
1188 {
1190 config->setScaleY(config->scaleY() * -1);
1191 }
1192
1195}
1196
1198{
1200
1201 {
1203 config->setAZ(normalizeAngle(config->aZ() + M_PI_2));
1204 }
1205
1208}
1209
1211{
1213
1214 {
1216 config->setAZ(normalizeAngle(config->aZ() - M_PI_2));
1217 }
1218
1221}
1222
1223
1224// change free transform setting we want to alter (all radio buttons call this)
1226{
1227 Q_UNUSED(value);
1228
1229 //QCheckBox sender = (QCheckBox)(*)(QObject::sender());
1230 QString senderName = QObject::sender()->objectName();
1231
1232
1233 // only show setting with what we have selected
1234 rotationGroup->hide();
1235 shearGroup->hide();
1236 scaleGroup->hide();
1237 moveGroup->hide();
1238
1239
1240 if ("freeMoveRadioButton" == senderName)
1241 {
1242 moveGroup->show();
1243 }
1244 else if ("freeShearRadioButton" == senderName)
1245 {
1246 shearGroup->show();
1247 }
1248 else if ("freeScaleRadioButton" == senderName)
1249 {
1250 scaleGroup->show();
1251 }
1252 else
1253 {
1254 rotationGroup->show();
1255 }
1256
1257}
1258
1260{
1261 if (m_uiSlotsBlocked) return;
1262
1264 config->setKeepAspectRatio(value);
1265
1266 if (value) {
1268 int tmpXScaleBox = scaleXBox->value();
1269 int tmpYScaleBox = scaleYBox->value();
1270 m_scaleRatio = (tmpXScaleBox / (double) tmpYScaleBox);
1272 }
1273
1274 blockUiSlots();
1275 aspectButton->setKeepAspectRatio(value);
1277
1279}
1280
1282{
1283 if (m_uiSlotsBlocked) return;
1284
1286
1287 config->setAlpha((double)value);
1290}
1291
1297
1305
1307{
1309
1310 densityBox->setEnabled(!enabled);
1311 customWarpWidget->setEnabled(enabled);
1312
1313 if (!enabled) {
1314 config->setEditingTransformPoints(false);
1315 setDefaultWarpPoints(densityBox->value());
1316 config->setWarpCalculation(KisWarpTransformWorker::WarpCalculation::GRID);
1317 } else {
1318 config->setEditingTransformPoints(true);
1319 config->setWarpCalculation(KisWarpTransformWorker::WarpCalculation::DRAW);
1321 }
1322
1323
1324
1325
1327}
1328
1335
1342
1349
1351{
1352 if (m_uiSlotsBlocked) return;
1353
1356
1357 if (config->isEditingTransformPoints()) {
1358 // reinit the transf points to their original value
1360 int nbPoints = config->origPoints().size();
1361 for (int i = 0; i < nbPoints; ++i) {
1362 config->transfPoint(i) = config->origPoint(i);
1363 }
1364 }
1365
1368}
1369
1371{
1372 if (m_uiSlotsBlocked) return;
1373
1375
1376 switch (index) {
1381 break;
1382 default:
1384 break;
1385 }
1386
1388}
1389
1391{
1392 if ( value == 0)
1393 {
1394 slotEditCagePoints(true);
1395 }
1396 else
1397 {
1398 slotEditCagePoints(false);
1399 }
1400
1402}
1403
1405{
1406 if (m_uiSlotsBlocked) return;
1407
1409 config->refTransformedPoints() = config->origPoints();
1410
1413}
1414
1423
1432
1434{
1435 if (m_uiSlotsBlocked) return;
1436
1438 KisBezierTransformMesh &mesh = *config->meshTransform();
1439
1440 if (mesh.size().width() != intNumColumns->value() + 1) {
1441 mesh.reshapeMeshHorizontally(intNumColumns->value() + 1);
1442 }
1443
1444 if (mesh.size().height() != intNumRows->value() + 1) {
1445 mesh.reshapeMeshVertically(intNumRows->value() + 1);
1446 }
1447
1449}
1450
1452{
1453 if (m_uiSlotsBlocked) return;
1455 config->setMeshShowHandles(this->chkShowControlPoints->isChecked());
1458}
1459
1461{
1462 if (m_uiSlotsBlocked) return;
1464 config->setMeshSymmetricalHandles(this->chkSymmetricalHandles->isChecked());
1467}
1468
1470{
1471 if (m_uiSlotsBlocked) return;
1473 config->setMeshScaleHandles(this->chkScaleHandles->isChecked());
1476}
1477
1479{
1480 KConfigGroup group = KSharedConfig::openConfig()->group("KisToolTransform");
1481 switch(index) {
1482 case 0:
1483 group.writeEntry("useOverlayPreviewStyle", false);
1484 group.writeEntry("forceLodMode", false);
1485 break;
1486 case 1:
1487 group.writeEntry("useOverlayPreviewStyle", false);
1488 group.writeEntry("forceLodMode", true);
1489 break;
1490 default:
1491 group.writeEntry("useOverlayPreviewStyle", true);
1492 }
1493
1499 Q_EMIT sigUpdateGlobalConfig();
1501}
float value(const T *src, size_t ch)
@ IncreasingDirection_Clockwise
@ FlipOptionsMode_MenuButton
The flip options are shown as a menu accessible via a options button.
void reshapeMeshVertically(int numRows)
void reshapeMeshHorizontally(int numColumns)
KisViewManager * viewManager() const
static KisFilterStrategyRegistry * instance()
void setMode(LiquifyMode value)
void setReverseDirection(bool value)
static bool supportsReverseDirection(LiquifyMode mode)
static bool supportsWashMode(LiquifyMode mode)
void setPreserveShapeStretch(bool value)
void setSizeHasPressure(bool value)
void setPreserveShapeScale(bool value)
void setPreserveShapeRotation(bool value)
void setAmountHasPressure(bool value)
The KisSignalMapper class bundles signals from identifiable senders.
void setMapping(QObject *sender, int id)
void sigResetTransform(ToolTransformArgs::TransformMode mode)
void slotButtonBoxClicked(QAbstractButton *button)
TransformTransactionProperties * m_transaction
void sigConfigChanged(bool needsPreviewRecalculation)
void notifyConfigChanged(bool needsPreviewRecalculation=true)
void updateConfig(const ToolTransformArgs &config)
KisToolTransformConfigWidget(TransformTransactionProperties *transaction, KisCanvas2 *canvas, QWidget *parent)
static void setDefaultWarpPoints(int pointsPerLine, const TransformTransactionProperties *transaction, ToolTransformArgs *config)
KisMainWindow * mainWindow() const
enum KisWarpTransformWorker::WarpType_ WarpType
Definition KoID.h:30
QString id() const
Definition KoID.cpp:63
void setCameraPos(const QVector3D &pos)
void setShearX(double shearX)
QPointF transformedCenter() const
bool meshScaleHandles() const
void setFilterId(const QString &id)
void setWarpCalculation(KisWarpTransformWorker::WarpCalculation warpCalc)
const QVector< QPointF > & origPoints() const
void setKeepAspectRatio(bool value)
QPointF & origPoint(int i)
QVector< QPointF > & refTransformedPoints()
void setTransformAroundRotationCenter(bool value)
bool transformAroundRotationCenter() const
void setRotationCenterOffset(QPointF rotationCenterOffset)
int previewPixelPrecision() const
bool isEditingTransformPoints() const
void setAlpha(double alpha)
void setScaleX(double scaleX)
KisWarpTransformWorker::WarpType warpType() const
void setMeshShowHandles(bool value)
void setTransformedCenter(QPointF transformedCenter)
void setPreviewPixelPrecision(int precision)
const KisLiquifyProperties * liquifyProperties() const
void setScaleY(double scaleY)
void setMeshScaleHandles(bool meshScaleHandles)
bool meshSymmetricalHandles() const
QPointF originalCenter() const
void setMeshSymmetricalHandles(bool meshSymmetricalHandles)
QPointF rotationCenterOffset() const
void setShearY(double shearY)
const KisBezierTransformMesh * meshTransform() const
void setEditingTransformPoints(bool value)
QPointF & transfPoint(int i)
void setPixelPrecision(int precision)
QString filterId() const
void setWarpType(KisWarpTransformWorker::WarpType warpType)
TransformMode mode() const
QVector3D cameraPos() const
static bool qFuzzyCompare(half p1, half p2)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
T kisRadiansToDegrees(T radians)
Definition kis_global.h:181
std::enable_if< std::is_floating_point< T >::value, T >::type normalizeAngleDegrees(T a)
Definition kis_global.h:132
T kisDegreesToRadians(T degrees)
Definition kis_global.h:176
std::enable_if< std::is_floating_point< T >::value, T >::type normalizeAngle(T a)
Definition kis_global.h:121
QString button(const QWheelEvent &ev)
QIcon loadIcon(const QString &name)
void setText(QSpinBox *spinBox, const QStringView textTemplate)