File indexing completed on 2024-06-16 04:12:07
0001 /* 0002 * SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KIS_PAINTOP_SETTINGS_H_ 0008 #define KIS_PAINTOP_SETTINGS_H_ 0009 0010 #include "kis_types.h" 0011 #include "kritaimage_export.h" 0012 0013 #include <QImage> 0014 #include <QScopedPointer> 0015 0016 #include "kis_properties_configuration.h" 0017 #include <brushengine/kis_paint_information.h> 0018 #include <brushengine/kis_uniform_paintop_property.h> 0019 0020 class KisPaintOpConfigWidget; 0021 class KisPaintOpPresetUpdateProxy; 0022 0023 class KisResourcesInterface; 0024 using KisResourcesInterfaceSP = QSharedPointer<KisResourcesInterface>; 0025 0026 class KoCanvasResourcesInterface; 0027 using KoCanvasResourcesInterfaceSP = QSharedPointer<KoCanvasResourcesInterface>; 0028 0029 class KoResourceCacheInterface; 0030 using KoResourceCacheInterfaceSP = QSharedPointer<KoResourceCacheInterface>; 0031 0032 class KisOptimizedBrushOutline; 0033 0034 /** 0035 * Configuration property used to control whether airbrushing is enabled. 0036 */ 0037 const QString AIRBRUSH_ENABLED = "PaintOpSettings/isAirbrushing"; 0038 0039 /** 0040 * Configuration property used to control airbrushing rate. The value should be in dabs per second. 0041 */ 0042 const QString AIRBRUSH_RATE = "PaintOpSettings/rate"; 0043 0044 /** 0045 * Configuration property used to control whether airbrushing is configured to ignore distance-based 0046 * spacing. 0047 */ 0048 const QString AIRBRUSH_IGNORE_SPACING = "PaintOpSettings/ignoreSpacing"; 0049 0050 /** 0051 * Configuration property used to control whether the spacing settings can be updated between 0052 * painted dabs. 0053 */ 0054 const QString SPACING_USE_UPDATES = "PaintOpSettings/updateSpacingBetweenDabs"; 0055 0056 /** 0057 * This class is used to cache the settings for a paintop 0058 * between two creations. There is one KisPaintOpSettings per input device (mouse, tablet, 0059 * etc...). 0060 * 0061 * The settings may be stored in a preset. Note that if your 0062 * paintop's settings subclass has data that is not stored as a property, that data is not 0063 * saved and restored. 0064 * 0065 * The object also contains a pointer to its parent KisPaintOpPreset object.This is to control the DirtyPreset 0066 * property of KisPaintOpPreset. Whenever the settings are changed/modified from the original -- the preset is 0067 * set to dirty. 0068 */ 0069 class KRITAIMAGE_EXPORT KisPaintOpSettings : public KisPropertiesConfiguration 0070 { 0071 public: 0072 struct UpdateListener { 0073 virtual ~UpdateListener(); 0074 virtual void setDirty(bool value) = 0; 0075 virtual bool isDirty() const = 0; 0076 virtual void notifySettingsChanged() = 0; 0077 }; 0078 0079 using UpdateListenerSP = QSharedPointer<UpdateListener>; 0080 using UpdateListenerWSP = QWeakPointer<UpdateListener>; 0081 0082 public: 0083 0084 KisPaintOpSettings(KisResourcesInterfaceSP resourcesInterface); 0085 ~KisPaintOpSettings() override; 0086 KisPaintOpSettings(const KisPaintOpSettings &rhs); 0087 0088 /** 0089 * This function is called by a tool when the mouse is pressed. It's useful if 0090 * the paintop needs mouse interaction for instance in the case of the clone op. 0091 * If the tool is supposed to ignore the event, the paint op should return true 0092 * and if the tool is supposed to use the event, return false. 0093 * See kis_tool_freehand:tryPickByPaintOp() 0094 */ 0095 virtual bool mousePressEvent(const KisPaintInformation &paintInformation, Qt::KeyboardModifiers modifiers, KisNodeWSP currentNode); 0096 /** 0097 * This function is called by a tool when the mouse is released. It's useful if 0098 * the paintop needs mouse interaction for instance in the case of the clone op. 0099 * If the tool is supposed to ignore the event, the paint op should return true 0100 * and if the tool is supposed to use the event, return false. 0101 */ 0102 virtual bool mouseReleaseEvent(); 0103 /** 0104 * Clone the current settings object. Override this if your settings instance doesn't 0105 * store everything as properties. 0106 */ 0107 virtual KisPaintOpSettingsSP clone() const; 0108 0109 /** 0110 * Removes all the settings from the object while keeping the paintop id, 0111 * which is loaded to the object by the factory 0112 */ 0113 virtual void resetSettings(const QStringList &preserveProperties = QStringList()); 0114 0115 /** 0116 * @return the node the paintop is working on. 0117 */ 0118 KisNodeSP node() const; 0119 0120 /** 0121 * Call this function when the paint op is selected or the tool is activated 0122 */ 0123 virtual void activate(); 0124 0125 /** 0126 * XXX: Remove this after 2.0, when the paint operation (incremental/non incremental) will 0127 * be completely handled in the paintop, not in the tool. This is a filthy hack to move 0128 * the option to the right place, at least. 0129 * @return true if we paint incrementally, false if we paint like Photoshop. By default, paintops 0130 * do not support non-incremental. 0131 */ 0132 virtual bool paintIncremental() { 0133 return true; 0134 } 0135 0136 /** 0137 * @return the composite op it to which the indirect painting device 0138 * should be initialized to. This is used by clone op to reset 0139 * the composite op to COMPOSITE_COPY 0140 */ 0141 virtual QString indirectPaintingCompositeOp() const; 0142 0143 /** 0144 * Whether this paintop wants to deposit paint even when not moving, i.e. the tool needs to 0145 * activate its timer. If this is true, painting updates need to be generated at regular 0146 * intervals even in the absence of input device events, e.g. when the cursor is not moving. 0147 * 0148 * The default implementation checks the property AIRBRUSH_ENABLED, defaulting to false if the 0149 * property is not found. This should be suitable for most paintops. 0150 */ 0151 virtual bool isAirbrushing() const; 0152 0153 /** 0154 * Indicates the minimum time interval that might be needed between airbrush dabs, in 0155 * milliseconds. A lower value means painting updates need to happen more frequently. This value 0156 * should be ignored if isAirbrushing() is false. 0157 * 0158 * The default implementation uses the property AIRBRUSH_RATE, defaulting to an interval of 0159 * one second if the property is not found. This should be suitable for most paintops. 0160 */ 0161 virtual qreal airbrushInterval() const; 0162 0163 /** 0164 * Indicates whether this configuration allows spacing information to be updated between painted 0165 * dabs during a stroke. 0166 */ 0167 virtual bool useSpacingUpdates() const; 0168 0169 /** 0170 * Indicates if the tool should call paintOp->doAsynchronousUpdate() in between 0171 * paintAt() calls to do the asynchronous rendering 0172 */ 0173 virtual bool needsAsynchronousUpdates() const; 0174 0175 /** 0176 * This structure defines the current mode for painting an outline. 0177 */ 0178 struct OutlineMode { 0179 bool isVisible = false; 0180 bool forceCircle = false; 0181 bool showTiltDecoration = false; 0182 bool forceFullSize = false; 0183 }; 0184 0185 /** 0186 * Returns the brush outline in pixel coordinates. Tool is responsible for conversion into view coordinates. 0187 * Outline mode has to be passed to the paintop which builds the outline as some paintops have to paint outline 0188 * always like clone paintop indicating the duplicate position 0189 */ 0190 virtual KisOptimizedBrushOutline brushOutline(const KisPaintInformation &info, const OutlineMode &mode, qreal alignForZoom); 0191 0192 /** 0193 * Helpers for drawing the brush outline 0194 */ 0195 static KisOptimizedBrushOutline ellipseOutline(qreal width, qreal height, qreal scale, qreal rotation); 0196 0197 /** 0198 * Helper for drawing a triangle representing the tilt of the stylus. 0199 * 0200 * @param start is the offset from the brush's outline's bounding box 0201 * @param lengthScale is used for deciding the size of the triangle. 0202 * Brush diameter or width are common choices for this. 0203 * @param angle is the angle between the two sides of the triangle. 0204 */ 0205 static QPainterPath makeTiltIndicator(KisPaintInformation const& info, 0206 QPointF const& start, qreal lengthScale, qreal angle); 0207 0208 /** 0209 * Set paintop opacity directly in the properties 0210 */ 0211 virtual void setPaintOpOpacity(qreal value); 0212 0213 /** 0214 * Set paintop flow directly in the properties 0215 */ 0216 void setPaintOpFlow(qreal value); 0217 0218 /** 0219 * Set paintop fade directly in the properties 0220 */ 0221 void setPaintOpFade(qreal value); 0222 0223 /** 0224 * Set paintop scatter directly in the properties 0225 */ 0226 void setPaintOpScatter(qreal value); 0227 0228 /** 0229 * Set paintop composite mode directly in the properties 0230 */ 0231 void setPaintOpCompositeOp(const QString &value); 0232 0233 /** 0234 * @return opacity saved in the properties 0235 */ 0236 virtual qreal paintOpOpacity(); 0237 0238 /** 0239 * @return flow saved in the properties 0240 */ 0241 qreal paintOpFlow(); 0242 0243 /** 0244 * @return fade saved in the properties 0245 */ 0246 qreal paintOpFade(); 0247 0248 /** 0249 * @return scatter saved in the properties 0250 */ 0251 qreal paintOpScatter(); 0252 0253 /** 0254 * @return composite mode saved in the properties 0255 */ 0256 QString paintOpCompositeOp(); 0257 0258 /** 0259 * Set paintop size directly in the properties 0260 */ 0261 virtual void setPaintOpSize(qreal value) = 0; 0262 0263 /** 0264 * @return size saved in the properties 0265 */ 0266 virtual qreal paintOpSize() const = 0; 0267 0268 /** 0269 * Set paintop angle (in degrees) directly in the properties. 0270 * Increasing the angle corresponds to a counter-clockwise rotation. 0271 */ 0272 virtual void setPaintOpAngle(qreal value) = 0; 0273 0274 /** 0275 * @return paintop angle (in degrees) saved in the properties 0276 */ 0277 virtual qreal paintOpAngle() const = 0; 0278 0279 /** 0280 * @return pattern size saved in the properties 0281 */ 0282 virtual qreal paintOpPatternSize(); 0283 0284 void setEraserMode(bool value); 0285 bool eraserMode(); 0286 0287 qreal savedEraserSize() const; 0288 void setSavedEraserSize(qreal value); 0289 qreal savedBrushSize() const; 0290 void setSavedBrushSize(qreal value); 0291 0292 qreal savedEraserOpacity() const; 0293 void setSavedEraserOpacity(qreal value); 0294 qreal savedBrushOpacity() const; 0295 void setSavedBrushOpacity(qreal value); 0296 0297 QString effectivePaintOpCompositeOp(); 0298 0299 void setUpdateListener(UpdateListenerWSP listener); 0300 0301 UpdateListenerWSP updateListener() const; 0302 0303 /** 0304 * @return filename of the 3D brush model, empty if no brush is set 0305 */ 0306 virtual QString modelName() const; 0307 0308 /** 0309 * Set filename of 3D brush model. By default no brush is set 0310 */ 0311 void setModelName(const QString & modelName); 0312 0313 /// Check if the settings are valid, setting might be invalid through missing brushes etc 0314 /// Overwrite if the settings of a paintop can be invalid 0315 /// @return state of the settings, default implementation is true 0316 virtual bool isValid() const; 0317 0318 /** 0319 * Overrides the method in KisPropertiesConfiguration to allow 0320 * onPropertyChanged() callback 0321 */ 0322 void setProperty(const QString & name, const QVariant & value) override; 0323 0324 virtual QList<KisUniformPaintOpPropertySP> uniformProperties(KisPaintOpSettingsSP settings, QPointer<KisPaintOpPresetUpdateProxy> updateProxy); 0325 0326 static bool isLodUserAllowed(const KisPropertiesConfigurationSP config); 0327 static void setLodUserAllowed(KisPropertiesConfigurationSP config, bool value); 0328 0329 virtual bool lodSizeThresholdSupported() const; 0330 0331 qreal lodSizeThreshold() const; 0332 void setLodSizeThreshold(qreal value); 0333 0334 /** 0335 * This function is called to set random offsets to the brush whenever the mouse is clicked. It is 0336 * specific to when the pattern option is set. 0337 * 0338 */ 0339 virtual void setRandomOffset(const KisPaintInformation &paintInformation); 0340 0341 /** 0342 * @return true if this preset demands a secondary masked brush running 0343 * alongside it 0344 */ 0345 bool hasMaskingSettings() const; 0346 0347 /** 0348 * @return a newly created settings object representing a preset of the masking 0349 * brush that should be run alongside the current brush 0350 */ 0351 KisPaintOpSettingsSP createMaskingSettings() const; 0352 0353 /** 0354 * @return a composite op id of the masked brush rendering algorithm. 0355 * 0356 * Please take into account that the brush itself always paints in alpha- 0357 * darken mode, but the final result is combined with this composite op. 0358 */ 0359 QString maskingBrushCompositeOp() const; 0360 0361 /** 0362 * @return resource interface that is used for loading linked resources 0363 */ 0364 KisResourcesInterfaceSP resourcesInterface() const; 0365 0366 /** 0367 * Set resource interface that will be used for loading linked resources 0368 */ 0369 void setResourcesInterface(KisResourcesInterfaceSP resourcesInterface); 0370 0371 0372 virtual bool hasPatternSettings() const; 0373 0374 virtual QList<int> requiredCanvasResources() const; 0375 0376 KoCanvasResourcesInterfaceSP canvasResourcesInterface() const; 0377 void setCanvasResourcesInterface(KoCanvasResourcesInterfaceSP canvasResourcesInterface); 0378 0379 virtual void setResourceCacheInterface(KoResourceCacheInterfaceSP cacheInterface); 0380 KoResourceCacheInterfaceSP resourceCacheInterface() const; 0381 0382 virtual void regenerateResourceCache(KoResourceCacheInterfaceSP cacheInterface); 0383 0384 quint64 sanityVersionCookie() const; 0385 0386 protected: 0387 0388 /** 0389 * The callback is called every time when a property changes 0390 */ 0391 virtual void onPropertyChanged(); 0392 0393 private: 0394 0395 0396 0397 struct Private; 0398 const QScopedPointer<Private> d; 0399 }; 0400 0401 #endif