File indexing completed on 2024-06-16 04:17:20

0001 /*
0002  *  SPDX-FileCopyrightText: 2008, 2009, 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include <KisOptimizedBrushOutline.h>
0008 #include <kis_deform_paintop_settings.h>
0009 #include <kis_deform_paintop_settings_widget.h>
0010 
0011 #include "KisBrushSizeOptionData.h"
0012 
0013 #include "KisDeformOptionData.h"
0014 
0015 struct KisDeformPaintOpSettings::Private
0016 {
0017     QList<KisUniformPaintOpPropertyWSP> uniformProperties;
0018 };
0019 
0020 KisDeformPaintOpSettings::KisDeformPaintOpSettings(KisResourcesInterfaceSP resourcesInterface)
0021     : KisOutlineGenerationPolicy<KisPaintOpSettings>(KisCurrentOutlineFetcher::SIZE_OPTION |
0022                                                      KisCurrentOutlineFetcher::ROTATION_OPTION,
0023                                                      resourcesInterface),
0024     m_d(new Private)
0025 {
0026 }
0027 
0028 KisDeformPaintOpSettings::~KisDeformPaintOpSettings()
0029 {
0030 }
0031 
0032 void KisDeformPaintOpSettings::setPaintOpSize(qreal value)
0033 {
0034     KisBrushSizeOptionData option;
0035     option.read(this);
0036     option.brushDiameter = value;
0037     option.write(this);
0038 }
0039 
0040 qreal KisDeformPaintOpSettings::paintOpSize() const
0041 {
0042     KisBrushSizeOptionData option;
0043     option.read(this);
0044     return option.brushDiameter;
0045 }
0046 
0047 void KisDeformPaintOpSettings::setPaintOpAngle(qreal value)
0048 {
0049     Q_UNUSED(value);
0050 }
0051 
0052 qreal KisDeformPaintOpSettings::paintOpAngle() const
0053 {
0054     return 0.0;
0055 }
0056 
0057 bool KisDeformPaintOpSettings::paintIncremental()
0058 {
0059     return true;
0060 }
0061 
0062 bool KisDeformPaintOpSettings::isAirbrushing() const
0063 {
0064     // version 2.3
0065     if (hasProperty(AIRBRUSH_ENABLED)) {
0066         return getBool(AIRBRUSH_ENABLED);
0067     }
0068     else {
0069         return getBool("Deform/useMovementPaint");
0070     }
0071 }
0072 
0073 KisOptimizedBrushOutline KisDeformPaintOpSettings::brushOutline(const KisPaintInformation &info, const OutlineMode &mode, qreal alignForZoom)
0074 {
0075     KisOptimizedBrushOutline path;
0076     if (mode.isVisible) {
0077         qreal width = getInt("Brush/diameter");
0078         qreal height = getInt("Brush/diameter") * getDouble("Brush/aspect");
0079         path = ellipseOutline(width, height, getDouble("Brush/scale"), -getDouble("Brush/rotation"));
0080 
0081         path = outlineFetcher()->fetchOutline(info, this, path, mode, alignForZoom);
0082 
0083         if (mode.showTiltDecoration) {
0084             QPainterPath tiltLine = makeTiltIndicator(info, QPointF(0.0, 0.0), width * 0.5, 3.0);
0085             path.addPath(outlineFetcher()->fetchOutline(info, this, tiltLine, mode, alignForZoom, 1.0, 0.0, true, 0, 0));
0086         }
0087     }
0088     return path;
0089 }
0090 
0091 
0092 #include <brushengine/kis_slider_based_paintop_property.h>
0093 #include <brushengine/kis_combo_based_paintop_property.h>
0094 #include "kis_paintop_preset.h"
0095 #include "KisPaintOpPresetUpdateProxy.h"
0096 #include "kis_standard_uniform_properties_factory.h"
0097 
0098 
0099 QList<KisUniformPaintOpPropertySP> KisDeformPaintOpSettings::uniformProperties(KisPaintOpSettingsSP settings, QPointer<KisPaintOpPresetUpdateProxy> updateProxy)
0100 {
0101     QList<KisUniformPaintOpPropertySP> props =
0102         listWeakToStrong(m_d->uniformProperties);
0103 
0104     if (props.isEmpty()) {
0105         {
0106             KisDoubleSliderBasedPaintOpPropertyCallback *prop =
0107                 new KisDoubleSliderBasedPaintOpPropertyCallback(KisDoubleSliderBasedPaintOpPropertyCallback::Double,
0108                                                                 KoID("deform_amount", i18n("Amount")),
0109                                                                 settings,
0110                                                                 0);
0111 
0112             prop->setRange(0.01, 1.0);
0113             prop->setSingleStep(0.01);
0114             prop->setDecimals(2);
0115 
0116             prop->setReadCallback(
0117                 [](KisUniformPaintOpProperty *prop) {
0118                     KisDeformOptionData option;
0119                     option.read(prop->settings().data());
0120                     prop->setValue(option.deformAmount);
0121                 });
0122             prop->setWriteCallback(
0123                 [](KisUniformPaintOpProperty *prop) {
0124                     KisDeformOptionData option;
0125                     option.read(prop->settings().data());
0126                     option.deformAmount = prop->value().toReal();
0127                     option.write(prop->settings().data());
0128                 });
0129 
0130             QObject::connect(updateProxy, SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue()));
0131             prop->requestReadValue();
0132             props << toQShared(prop);
0133         }
0134 
0135         {
0136             KisComboBasedPaintOpPropertyCallback *prop = new KisComboBasedPaintOpPropertyCallback(KoID("deform_mode", i18n("Deform Mode")), settings, 0);
0137 
0138             QList<QString> modes;
0139             modes << i18nc("Grow as in deform brush engine", "Grow");
0140             modes << i18nc("Shrink as in deform brush engine", "Shrink");
0141             modes << i18n("Swirl CW");
0142             modes << i18n("Swirl CCW");
0143             modes << i18n("Move");
0144             modes << i18n("Lens Zoom In");
0145             modes << i18n("Lens Zoom Out");
0146             modes << i18nc("Rearrange the positions of the pixels under the cursor", "Color Deformation");
0147 
0148             prop->setItems(modes);
0149 
0150             prop->setReadCallback(
0151                 [](KisUniformPaintOpProperty *prop) {
0152                     KisDeformOptionData option;
0153                     option.read(prop->settings().data());
0154                     prop->setValue(int(option.deformAction));
0155                 });
0156             prop->setWriteCallback(
0157                 [](KisUniformPaintOpProperty *prop) {
0158                     KisDeformOptionData option;
0159                     option.read(prop->settings().data());
0160                     option.deformAction = (DeformModes)prop->value().toInt();
0161                     option.write(prop->settings().data());
0162                 });
0163 
0164             QObject::connect(updateProxy, SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue()));
0165             prop->requestReadValue();
0166             props << toQShared(prop);
0167         }
0168 
0169 
0170         {
0171             KisIntSliderBasedPaintOpPropertyCallback *prop =
0172                 new KisIntSliderBasedPaintOpPropertyCallback(KisIntSliderBasedPaintOpPropertyCallback::Int,
0173                                                              KisIntSliderBasedPaintOpPropertyCallback::SubType_Angle,
0174                                                              KoID("deform_angle", i18n("Angle")),
0175                                                              settings,
0176                                                              0);
0177 
0178             const QString degree = QChar(Qt::Key_degree);
0179             prop->setRange(0, 360);
0180             prop->setSingleStep(1);
0181             prop->setSuffix(degree);
0182 
0183             prop->setReadCallback(
0184                 [](KisUniformPaintOpProperty *prop) {
0185                     KisBrushSizeOptionData option;
0186                     option.read(prop->settings().data());
0187 
0188                     prop->setValue(int(option.brushRotation));
0189                 });
0190             prop->setWriteCallback(
0191                 [](KisUniformPaintOpProperty *prop) {
0192                     KisBrushSizeOptionData option;
0193                     option.read(prop->settings().data());
0194                     option.brushRotation = prop->value().toInt();
0195                     option.write(prop->settings().data());
0196                 });
0197 
0198             QObject::connect(updateProxy, SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue()));
0199             prop->requestReadValue();
0200             props << toQShared(prop);
0201         }
0202     }
0203 
0204     {
0205         using namespace KisStandardUniformPropertiesFactory;
0206 
0207         Q_FOREACH (KisUniformPaintOpPropertySP prop, KisPaintOpSettings::uniformProperties(settings, updateProxy)) {
0208             if (prop->id() == opacity.id() ||
0209                 prop->id() == size.id()) {
0210                 props.prepend(prop);
0211             }
0212         }
0213     }
0214 
0215     return props;
0216 }