Krita Source Code Documentation
Loading...
Searching...
No Matches
KisCurveOption.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2008 Boudewijn Rempt <boud@valdyas.org>
3 * SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de>
4 * SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8#include "KisCurveOption.h"
10#include "kis_algebra_2d.h"
11
18
19namespace {
20template <typename Sensor, typename Data, typename... Args>
21void addSensor(std::vector<std::unique_ptr<KisDynamicSensor>> &sensors,
22 const Data &data, std::optional<KisCubicCurve> commonCurve, Args... args)
23{
24 if (data.isActive) {
25 sensors.push_back(std::unique_ptr<KisDynamicSensor>(new Sensor(data, commonCurve, args...)));
26 }
27}
28
29std::vector<std::unique_ptr<KisDynamicSensor>> generateSensors(const KisCurveOptionData &data)
30{
31 std::vector<std::unique_ptr<KisDynamicSensor>> result;
32
33 std::optional<KisCubicCurve> commonCurve;
34 if (data.useSameCurve) {
35 commonCurve = KisCubicCurve(data.commonCurve);
36 }
37
38 const KisKritaSensorData &sensorStruct = data.sensorStruct();
39
40 addSensor<KisDynamicSensorPressure>(result, sensorStruct.sensorPressure, commonCurve);
41 addSensor<KisDynamicSensorPressureIn>(result, sensorStruct.sensorPressureIn, commonCurve);
42 addSensor<KisDynamicSensorTangentialPressure>(result, sensorStruct.sensorTangentialPressure, commonCurve);
43 addSensor<KisDynamicSensorDrawingAngle>(result, sensorStruct.sensorDrawingAngle, commonCurve);
44 addSensor<KisDynamicSensorXTilt>(result, sensorStruct.sensorXTilt, commonCurve);
45 addSensor<KisDynamicSensorYTilt>(result, sensorStruct.sensorYTilt, commonCurve);
46 addSensor<KisDynamicSensorTiltDirection>(result, sensorStruct.sensorTiltDirection, commonCurve);
47 addSensor<KisDynamicSensorTiltElevation>(result, sensorStruct.sensorTiltElevation, commonCurve);
48 addSensor<KisDynamicSensorRotation>(result, sensorStruct.sensorRotation, commonCurve);
49 addSensor<KisDynamicSensorFuzzyPerDab>(result, sensorStruct.sensorFuzzyPerDab, commonCurve);
50 addSensor<KisDynamicSensorFuzzyPerStroke>(result, sensorStruct.sensorFuzzyPerStroke, commonCurve, data.id.id());
51 addSensor<KisDynamicSensorSpeed>(result, sensorStruct.sensorSpeed, commonCurve);
52 addSensor<KisDynamicSensorFade>(result, sensorStruct.sensorFade, commonCurve);
53 addSensor<KisDynamicSensorDistance>(result, sensorStruct.sensorDistance, commonCurve);
54 addSensor<KisDynamicSensorTime>(result, sensorStruct.sensorTime, commonCurve);
55 addSensor<KisDynamicSensorPerspective>(result, sensorStruct.sensorPerspective, commonCurve);
56
57 return result;
58}
59}
60
61qreal KisCurveOption::ValueComponents::rotationLikeValue(qreal normalizedBaseAngle, bool absoluteAxesFlipped, qreal scalingPartCoeff, bool disableScalingPart) const {
62 const qreal offset =
63 !hasAbsoluteOffset ? normalizedBaseAngle :
64 absoluteAxesFlipped ? 0.5 - absoluteOffset :
66
67 const qreal realScalingPart = hasScaling && !disableScalingPart ? KisDynamicSensor::scalingToAdditive(scaling) : 0.0;
68 const qreal realAdditivePart = hasAdditive ? additive : 0;
69
70 qreal value = KisAlgebra2D::wrapValue(2 * offset + constant * (scalingPartCoeff * realScalingPart + realAdditivePart), -1.0, 1.0);
71 if (qIsNaN(value)) {
72 qWarning() << "rotationLikeValue returns NaN!" << normalizedBaseAngle << absoluteAxesFlipped;
73 value = 0;
74 }
75 return value;
76}
77
79 const qreal offset =
80 hasAbsoluteOffset ? absoluteOffset : 1.0;
81
82 const qreal realScalingPart = hasScaling ? scaling : 1.0;
83 const qreal realAdditivePart = hasAdditive ? KisDynamicSensor::additiveToScaling(additive) : 1.0;
84
85 return qBound(minSizeLikeValue,
86 constant * offset * realScalingPart * realAdditivePart,
87 maxSizeLikeValue);
88}
89
90
93 , m_useCurve(data.useCurve)
94 , m_curveMode(data.curveMode)
98 , m_sensors(generateSensors(data))
99{
100}
101
103{
104 ValueComponents components;
105
106 if (m_useCurve) {
107 QList<double> sensorValues;
108 for (auto i = m_sensors.cbegin(); i != m_sensors.cend(); ++i) {
109 KisDynamicSensor *s(i->get());
110
111 qreal valueFromCurve = s->parameter(info);
112 if (s->isAdditive()) {
113 components.additive += valueFromCurve;
114 components.hasAdditive = true;
115 } else if (s->isAbsoluteRotation()) {
116 components.absoluteOffset = valueFromCurve;
117 components.hasAbsoluteOffset =true;
118 } else {
119 sensorValues << valueFromCurve;
120 components.hasScaling = true;
121 }
122 }
123
124 if (sensorValues.count() == 1) {
125 components.scaling = sensorValues.first();
126 } else if (sensorValues.count() > 1) {
127
128 if (m_curveMode == 1){ // add
129 components.scaling = 0;
130 double i;
131 foreach (i, sensorValues) {
132 components.scaling += i;
133 }
134 } else if (m_curveMode == 2){ //max
135 components.scaling = *std::max_element(sensorValues.begin(), sensorValues.end());
136
137 } else if (m_curveMode == 3){ //min
138 components.scaling = *std::min_element(sensorValues.begin(), sensorValues.end());
139
140 } else if (m_curveMode == 4){ //difference
141 double max = *std::max_element(sensorValues.begin(), sensorValues.end());
142 double min = *std::min_element(sensorValues.begin(), sensorValues.end());
143 components.scaling = max-min;
144
145 } else { //multiply - default
146 double i;
147 foreach (i, sensorValues) {
148 components.scaling *= i;
149 }
150 }
151 }
152
153 }
154
155 if (useStrengthValue) {
156 components.constant = m_strengthValue;
157 }
158
161
162 return components;
163}
164
165qreal KisCurveOption::computeSizeLikeValue(const KisPaintInformation& info, bool useStrengthValue) const
166{
167 const ValueComponents components = computeValueComponents(info, useStrengthValue);
168 return components.sizeLikeValue();
169}
170
171qreal KisCurveOption::computeRotationLikeValue(const KisPaintInformation& info, qreal baseValue, bool absoluteAxesFlipped, qreal scalingPartCoeff, bool disableScalingPart) const
172{
173 const ValueComponents components = computeValueComponents(info, true);
174 return components.rotationLikeValue(baseValue, absoluteAxesFlipped, scalingPartCoeff, disableScalingPart);
175}
176
178{
179 return m_strengthValue;
180}
181
183{
184 return m_strengthMinValue;
185}
186
188{
189 return m_strengthMaxValue;
190}
191
193{
194 return m_isChecked;
195}
196
198{
199 for (auto it = m_sensors.begin(); it != m_sensors.end(); ++it) {
200 const KisDynamicSensor *sensor = it->get();
201 if (sensor->id() == FuzzyPerDabId || sensor->id() == FuzzyPerStrokeId) return true;
202 }
203 return false;
204}
float value(const T *src, size_t ch)
const KoID FuzzyPerStrokeId("fuzzystroke", ki18nc("Context: dynamic sensors", "Fuzzy Stroke"))
generate a random number
const KoID FuzzyPerDabId("fuzzy", ki18nc("Context: dynamic sensors", "Fuzzy Dab"))
generate a random number
qreal strengthMinValue() const
qreal computeRotationLikeValue(const KisPaintInformation &info, qreal baseValue, bool absoluteAxesFlipped, qreal scalingPartCoeff, bool disableScalingPart) const
qreal strengthValue() const
bool isChecked() const
KisCurveOption(const KisCurveOptionData &data)
qreal computeSizeLikeValue(const KisPaintInformation &info, bool useStrengthValue=true) const
ValueComponents computeValueComponents(const KisPaintInformation &info, bool useStrengthValue) const
qreal strengthMaxValue() const
bool isRandom() const
std::vector< std::unique_ptr< KisDynamicSensor > > m_sensors
qreal parameter(const KisPaintInformation &info) const
static qreal additiveToScaling(qreal x)
virtual bool isAdditive() const
static qreal scalingToAdditive(qreal x)
virtual bool isAbsoluteRotation() const
QString id() const
Definition KoID.cpp:63
T wrapValue(T value, T wrapBounds)
std::vector< SensorData * > sensors(Data *data)
KisKritaSensorData & sensorStruct()
qreal rotationLikeValue(qreal normalizedBaseAngle, bool absoluteAxesFlipped, qreal scalingPartCoeff, bool disableScalingPart) const
KisSensorWithLengthData sensorTime
KisSensorData sensorYTilt
KisSensorWithLengthData sensorDistance
KisSensorData sensorTiltElevation
KisSensorData sensorPerspective
KisSensorData sensorTangentialPressure
KisSensorData sensorSpeed
KisSensorData sensorPressureIn
KisSensorData sensorRotation
KisSensorData sensorXTilt
KisSensorData sensorFuzzyPerStroke
KisSensorData sensorPressure
KisSensorData sensorTiltDirection
KisDrawingAngleSensorData sensorDrawingAngle
KisSensorData sensorFuzzyPerDab
KisSensorWithLengthData sensorFade