1 /* 2 * Copyright (c) 2007 Boudewijn Rempt <boud@valdyas.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 #ifndef KIS_PAINTOP_SETTINGS_H_ 20 #define KIS_PAINTOP_SETTINGS_H_ 21 22 #include "kis_types.h" 23 #include "kritaimage_export.h" 24 25 #include <QImage> 26 #include <QScopedPointer> 27 28 #include "kis_properties_configuration.h" 29 #include <brushengine/kis_paint_information.h> 30 #include <brushengine/kis_uniform_paintop_property.h> 31 32 33 34 class KisPaintOpConfigWidget; 35 class KisPaintopSettingsUpdateProxy; 36 37 /** 38 * Configuration property used to control whether airbrushing is enabled. 39 */ 40 const QString AIRBRUSH_ENABLED = "PaintOpSettings/isAirbrushing"; 41 42 /** 43 * Configuration property used to control airbrushing rate. The value should be in dabs per second. 44 */ 45 const QString AIRBRUSH_RATE = "PaintOpSettings/rate"; 46 47 /** 48 * Configuration property used to control whether airbrushing is configured to ignore distance-based 49 * spacing. 50 */ 51 const QString AIRBRUSH_IGNORE_SPACING = "PaintOpSettings/ignoreSpacing"; 52 53 /** 54 * Configuration property used to control whether the spacing settings can be updated between 55 * painted dabs. 56 */ 57 const QString SPACING_USE_UPDATES = "PaintOpSettings/updateSpacingBetweenDabs"; 58 59 /** 60 * This class is used to cache the settings for a paintop 61 * between two creations. There is one KisPaintOpSettings per input device (mouse, tablet, 62 * etc...). 63 * 64 * The settings may be stored in a preset. Note that if your 65 * paintop's settings subclass has data that is not stored as a property, that data is not 66 * saved and restored. 67 * 68 * The object also contains a pointer to its parent KisPaintOpPreset object.This is to control the DirtyPreset 69 * property of KisPaintOpPreset. Whenever the settings are changed/modified from the original -- the preset is 70 * set to dirty. 71 */ 72 class KRITAIMAGE_EXPORT KisPaintOpSettings : public KisPropertiesConfiguration 73 { 74 75 public: 76 77 KisPaintOpSettings(); 78 ~KisPaintOpSettings() override; 79 KisPaintOpSettings(const KisPaintOpSettings &rhs); 80 81 /** 82 * 83 */ 84 void setOptionsWidget(KisPaintOpConfigWidget* widget); 85 86 /** 87 * This function is called by a tool when the mouse is pressed. It's useful if 88 * the paintop needs mouse interaction for instance in the case of the clone op. 89 * If the tool is supposed to ignore the event, the paint op should return true 90 * and if the tool is supposed to use the event, return false. 91 * See kis_tool_freehand:tryPickByPaintOp() 92 */ 93 virtual bool mousePressEvent(const KisPaintInformation &paintInformation, Qt::KeyboardModifiers modifiers, KisNodeWSP currentNode); 94 /** 95 * This function is called by a tool when the mouse is released. It's useful if 96 * the paintop needs mouse interaction for instance in the case of the clone op. 97 * If the tool is supposed to ignore the event, the paint op should return true 98 * and if the tool is supposed to use the event, return false. 99 */ 100 virtual bool mouseReleaseEvent(); 101 /** 102 * Clone the current settings object. Override this if your settings instance doesn't 103 * store everything as properties. 104 */ 105 virtual KisPaintOpSettingsSP clone() const; 106 107 /** 108 * Removes all the settings from the object while keeping the paintop id, 109 * which is loaded to the object by the factory 110 */ 111 void resetSettings(const QStringList &preserveProperties = QStringList()); 112 113 /** 114 * @return the node the paintop is working on. 115 */ 116 KisNodeSP node() const; 117 118 /** 119 * Call this function when the paint op is selected or the tool is activated 120 */ 121 virtual void activate(); 122 123 /** 124 * XXX: Remove this after 2.0, when the paint operation (incremental/non incremental) will 125 * be completely handled in the paintop, not in the tool. This is a filthy hack to move 126 * the option to the right place, at least. 127 * @return true if we paint incrementally, false if we paint like Photoshop. By default, paintops 128 * do not support non-incremental. 129 */ paintIncremental()130 virtual bool paintIncremental() { 131 return true; 132 } 133 134 /** 135 * @return the composite op it to which the indirect painting device 136 * should be initialized to. This is used by clone op to reset 137 * the composite op to COMPOSITE_COPY 138 */ 139 virtual QString indirectPaintingCompositeOp() const; 140 141 /** 142 * Whether this paintop wants to deposit paint even when not moving, i.e. the tool needs to 143 * activate its timer. If this is true, painting updates need to be generated at regular 144 * intervals even in the absence of input device events, e.g. when the cursor is not moving. 145 * 146 * The default implementation checks the property AIRBRUSH_ENABLED, defaulting to false if the 147 * property is not found. This should be suitable for most paintops. 148 */ 149 virtual bool isAirbrushing() const; 150 151 /** 152 * Indicates the minimum time interval that might be needed between airbrush dabs, in 153 * milliseconds. A lower value means painting updates need to happen more frequently. This value 154 * should be ignored if isAirbrushing() is false. 155 * 156 * The default implementation uses the property AIRBRUSH_RATE, defaulting to an interval of 157 * one second if the property is not found. This should be suitable for most paintops. 158 */ 159 virtual qreal airbrushInterval() const; 160 161 /** 162 * Indicates whether this configuration allows spacing information to be updated between painted 163 * dabs during a stroke. 164 */ 165 virtual bool useSpacingUpdates() const; 166 167 /** 168 * Indicates if the tool should call paintOp->doAsynchronousUpdate() inbetween 169 * paintAt() calls to do the asynchronous rendering 170 */ 171 virtual bool needsAsynchronousUpdates() const; 172 173 /** 174 * This structure defines the current mode for painting an outline. 175 */ 176 struct OutlineMode { 177 bool isVisible = false; 178 bool forceCircle = false; 179 bool showTiltDecoration = false; 180 bool forceFullSize = false; 181 }; 182 183 /** 184 * Returns the brush outline in pixel coordinates. Tool is responsible for conversion into view coordinates. 185 * Outline mode has to be passed to the paintop which builds the outline as some paintops have to paint outline 186 * always like clone paintop indicating the duplicate position 187 */ 188 virtual QPainterPath brushOutline(const KisPaintInformation &info, const OutlineMode &mode, qreal alignForZoom); 189 190 /** 191 * Helpers for drawing the brush outline 192 */ 193 static QPainterPath ellipseOutline(qreal width, qreal height, qreal scale, qreal rotation); 194 195 /** 196 * Helper for drawing a triangle representing the tilt of the stylus. 197 * 198 * @param start is the offset from the brush's outline's bounding box 199 * @param lengthScale is used for deciding the size of the triangle. 200 * Brush diameter or width are common choices for this. 201 * @param angle is the angle between the two sides of the triangle. 202 */ 203 static QPainterPath makeTiltIndicator(KisPaintInformation const& info, 204 QPointF const& start, qreal lengthScale, qreal angle); 205 206 /** 207 * Set paintop opacity directly in the properties 208 */ 209 void setPaintOpOpacity(qreal value); 210 211 /** 212 * Set paintop flow directly in the properties 213 */ 214 void setPaintOpFlow(qreal value); 215 216 /** 217 * Set paintop composite mode directly in the properties 218 */ 219 void setPaintOpCompositeOp(const QString &value); 220 221 /** 222 * @return opacity saved in the properties 223 */ 224 qreal paintOpOpacity(); 225 226 /** 227 * @return flow saved in the properties 228 */ 229 qreal paintOpFlow(); 230 231 /** 232 * @return composite mode saved in the properties 233 */ 234 QString paintOpCompositeOp(); 235 236 /** 237 * Set paintop size directly in the properties 238 */ 239 virtual void setPaintOpSize(qreal value) = 0; 240 241 /** 242 * @return size saved in the properties 243 */ 244 virtual qreal paintOpSize() const = 0; 245 246 /** 247 * @return pattern size saved in the properties 248 */ 249 virtual qreal paintOpPatternSize(); 250 251 void setEraserMode(bool value); 252 bool eraserMode(); 253 254 qreal savedEraserSize() const; 255 void setSavedEraserSize(qreal value); 256 qreal savedBrushSize() const; 257 void setSavedBrushSize(qreal value); 258 259 qreal savedEraserOpacity() const; 260 void setSavedEraserOpacity(qreal value); 261 qreal savedBrushOpacity() const; 262 void setSavedBrushOpacity(qreal value); 263 264 QString effectivePaintOpCompositeOp(); 265 266 void setPreset(KisPaintOpPresetWSP preset); 267 268 KisPaintOpPresetWSP preset() const; 269 270 /** 271 * @return filename of the 3D brush model, empty if no brush is set 272 */ 273 virtual QString modelName() const; 274 275 /** 276 * Set filename of 3D brush model. By default no brush is set 277 */ 278 void setModelName(const QString & modelName); 279 280 /// Check if the settings are valid, setting might be invalid through missing brushes etc 281 /// Overwrite if the settings of a paintop can be invalid 282 /// @return state of the settings, default implementation is true 283 virtual bool isValid() const; 284 285 /// Check if the settings are loadable, that might the case if we can fallback to something 286 /// Overwrite if the settings can do some kind of fallback 287 /// @return loadable state of the settings, by default implementation return the same as isValid() 288 virtual bool isLoadable(); 289 290 /** 291 * Overrides the method in KisPropertiesCofiguration to allow 292 * onPropertyChanged() callback 293 */ 294 void setProperty(const QString & name, const QVariant & value) override; 295 296 virtual QList<KisUniformPaintOpPropertySP> uniformProperties(KisPaintOpSettingsSP settings); 297 298 static bool isLodUserAllowed(const KisPropertiesConfigurationSP config); 299 static void setLodUserAllowed(KisPropertiesConfigurationSP config, bool value); 300 301 virtual bool lodSizeThresholdSupported() const; 302 303 qreal lodSizeThreshold() const; 304 void setLodSizeThreshold(qreal value); 305 306 /** 307 * @return the option widget of the paintop (can be 0 is no option widgets is set) 308 */ 309 KisPaintOpConfigWidget* optionsWidget() const; 310 311 312 /** 313 * This function is called to set random offsets to the brush whenever the mouse is clicked. It is 314 * specific to when the pattern option is set. 315 * 316 */ 317 virtual void setRandomOffset(const KisPaintInformation &paintInformation); 318 319 /** 320 * @return true if this preset demands a secondary masked brush running 321 * alongside it 322 */ 323 bool hasMaskingSettings() const; 324 325 /** 326 * @return a newly created settings object representing a preset of the masking 327 * brush that should be run alongside the current brush 328 */ 329 KisPaintOpSettingsSP createMaskingSettings() const; 330 331 /** 332 * @return a composite op id of the masked brush rendering algorithm. 333 * 334 * Please take into account that the brush itself always paints in alpha- 335 * darken mode, but the final result is combined with this composite op. 336 */ 337 QString maskingBrushCompositeOp() const; 338 339 virtual bool hasPatternSettings() const; 340 341 protected: 342 343 /** 344 * The callback is called every time when a property changes 345 */ 346 virtual void onPropertyChanged(); 347 348 private: 349 350 351 352 struct Private; 353 const QScopedPointer<Private> d; 354 }; 355 356 #endif 357