Krita Source Code Documentation
Loading...
Searching...
No Matches
KisKritaSensorPack.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8#include "KisCppQuirks.h"
9#include "kis_assert.h"
10
11#include <QDomDocument>
12#include <QDomElement>
13
14#include <KisCurveOptionData.h>
15
16namespace detail {
17template <typename Data,
18 typename SensorData =
21inline std::vector<SensorData*> sensors(Data *data)
22{
23 std::vector<SensorData*> result;
24
25 result.reserve(16);
26
27 result.push_back(&data->sensorPressure);
28 result.push_back(&data->sensorPressureIn);
29 result.push_back(&data->sensorTangentialPressure);
30
31 result.push_back(&data->sensorDrawingAngle);
32 result.push_back(&data->sensorXTilt);
33 result.push_back(&data->sensorYTilt);
34 result.push_back(&data->sensorTiltDirection);
35 result.push_back(&data->sensorTiltElevation);
36 result.push_back(&data->sensorRotation);
37
38 result.push_back(&data->sensorFuzzyPerDab);
39 result.push_back(&data->sensorFuzzyPerStroke);
40
41 result.push_back(&data->sensorSpeed);
42 result.push_back(&data->sensorFade);
43 result.push_back(&data->sensorDistance);
44 result.push_back(&data->sensorTime);
45
46 result.push_back(&data->sensorPerspective);
47
48
49 return result;
50}
51} // namespace detail
52
54 : sensorPressure(PressureId),
55 sensorPressureIn(PressureInId),
56 sensorXTilt(XTiltId),
57 sensorYTilt(YTiltId),
58 sensorTiltDirection(TiltDirectionId),
59 sensorTiltElevation(TiltElevationId),
60 sensorSpeed(SpeedId),
61 sensorDrawingAngle(),
62 sensorRotation(RotationId),
63 sensorDistance(DistanceId),
64 sensorTime(TimeId, QLatin1String("duration")),
65 sensorFuzzyPerDab(FuzzyPerDabId),
66 sensorFuzzyPerStroke(FuzzyPerStrokeId),
67 sensorFade(FadeId),
68 sensorPerspective(PerspectiveId),
69 sensorTangentialPressure(TangentialPressureId)
70{
72}
73
75 : m_checkability(checkability)
76{
77}
78
83
84std::vector<const KisSensorData *> KisKritaSensorPack::constSensors() const
85{
86 return detail::sensors(&m_data);
87}
88
89std::vector<KisSensorData *> KisKritaSensorPack::sensors()
90{
91 return detail::sensors(&m_data);
92}
93
98
103
105{
106 const KisKritaSensorPack *pack = dynamic_cast<const KisKritaSensorPack*>(rhs);
109
110 return m_data == pack->m_data;
111}
112
114{
117 (!data.prefix.isEmpty() ||
119
120 data.isChecked = !data.isCheckable || setting->getBool("Pressure" + data.id.id(), false);
121
122 std::vector<KisSensorData*> sensors = data.sensors();
123 QMap<QString, KisSensorData*> sensorById;
124
125 Q_FOREACH (KisSensorData *sensor, sensors) {
126 sensorById.insert(sensor->id.id(), sensor);
127 }
128
129 QSet<KisSensorData*> sensorsToReset;
130
131 QList l = sensorById.values();
132 if (!l.isEmpty()) {
133 sensorsToReset = QSet<KisSensorData*>(l.begin(), l.end());
134 }
135
136 const QString sensorDefinition = setting->getString(data.id.id() + "Sensor");
137
138 if (sensorDefinition.isEmpty()) {
139 // noop
140 } else if (!sensorDefinition.contains("sensorslist")) {
141 QDomDocument doc;
142 doc.setContent(sensorDefinition);
143 QDomElement e = doc.documentElement();
144
145 const QString sensorId = e.attribute("id", "");
146 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!sensorId.isEmpty(), false);
147 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(sensorById.contains(sensorId), false);
148
149 KisSensorData *sensor = sensorById[sensorId];
150 sensor->read(e);
151 sensor->isActive = true;
152 sensorsToReset.remove(sensor);
153
154 data.commonCurve = sensor->curve;
155
156 } else {
157 QString proposedCommonCurve;
158
159 QDomDocument doc;
160 doc.setContent(sensorDefinition);
161 QDomElement elt = doc.documentElement();
162 QDomNode node = elt.firstChild();
163 while (!node.isNull()) {
164 if (node.isElement()) {
165 QDomElement childelt = node.toElement();
166 if (childelt.tagName() == "ChildSensor") {
167
168 const QString sensorId = childelt.attribute("id", "");
169 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!sensorId.isEmpty(), false);
170 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(sensorById.contains(sensorId), false);
171
172 KisSensorData *sensor = sensorById[sensorId];
173 sensor->read(childelt);
174 sensor->isActive = true;
175 sensorsToReset.remove(sensor);
176
179 proposedCommonCurve = sensor->curve;
180 }
181 }
182 node = node.nextSibling();
183 }
184
185 data.commonCurve = !proposedCommonCurve.isEmpty() ? proposedCommonCurve : DEFAULT_CURVE_STRING;
186 }
187
188 data.useSameCurve = setting->getBool(data.id.id() + "UseSameCurve", true);
189
190 // Only load the old curve format if the curve wasn't saved by the sensor
191 // This will give every sensor the same curve.
192 if (!sensorDefinition.contains("curve")) {
193 if (setting->getBool("Custom" + data.id.id(), false)) {
194 data.commonCurve = setting->getString("Curve" + data.id.id(), DEFAULT_CURVE_STRING);
195 Q_FOREACH (KisSensorData *sensor, sensors) {
196 sensor->curve = data.commonCurve;
197 sensorsToReset.remove(sensor);
198 }
199 } else {
201 }
202 }
203
204 if (data.useSameCurve) {
205 data.commonCurve = setting->getString(data.id.id() + "commonCurve",
206 !data.commonCurve.isEmpty() ?
207 data.commonCurve :
209 if (data.commonCurve.isEmpty()) {
211 }
212 }
213
214 Q_FOREACH (KisSensorData *sensor, sensorsToReset) {
215 sensor->reset();
216 }
217
218 // At least one sensor needs to be active
219 if (std::find_if(sensors.begin(), sensors.end(),
220 std::mem_fn(&KisSensorData::isActive)) == sensors.end()) {
221
222 sensorById[PressureId.id()]->isActive = true;
223 }
224
225 data.strengthValue = setting->getDouble(data.id.id() + "Value", data.strengthMaxValue);
226
227 if (data.valueFixUpReadCallback) {
228 data.valueFixUpReadCallback(&data, setting);
229 }
230
231 data.useCurve = setting->getBool(data.id.id() + "UseCurve", true);
232 data.curveMode = setting->getInt(data.id.id() + "curveMode", 0);
233
234 return true;
235}
236
238{
239 setting->setProperty("Pressure" + data.id.id(), data.isChecked || !data.isCheckable);
240
241 QVector<const KisSensorData*> activeSensors;
242 Q_FOREACH(const KisSensorData *sensor, data.sensors()) {
243 if (sensor->isActive) {
244 activeSensors.append(sensor);
245 }
246 }
247
248 QDomDocument doc = QDomDocument("params");
249 QDomElement root = doc.createElement("params");
250 doc.appendChild(root);
251
252 if (activeSensors.size() == 1) {
253 activeSensors.first()->write(doc, root);
254 } else {
255 root.setAttribute("id", "sensorslist");
256 Q_FOREACH (const KisSensorData *sensor, activeSensors) {
257 QDomElement childelt = doc.createElement("ChildSensor");
258 sensor->write(doc, childelt);
259 root.appendChild(childelt);
260 }
261 }
262 setting->setProperty(data.id.id() + "Sensor", doc.toString());
263
264 setting->setProperty(data.id.id() + "UseCurve", data.useCurve);
265 setting->setProperty(data.id.id() + "UseSameCurve", data.useSameCurve);
266 setting->setProperty(data.id.id() + "Value", data.strengthValue);
267 if (data.valueFixUpWriteCallback) {
268 data.valueFixUpWriteCallback(data.strengthValue, setting);
269 }
270 setting->setProperty(data.id.id() + "curveMode", data.curveMode);
271 setting->setProperty(data.id.id() + "commonCurve", data.commonCurve);
272}
273
274int KisKritaSensorPack::calcActiveSensorLength(const QString &activeSensorId) const
275{
276 if (activeSensorId == FadeId.id()) {
277 return m_data.sensorFade.length;
278 } else if (activeSensorId == DistanceId.id()) {
280 } else if (activeSensorId == TimeId.id()) {
281 return m_data.sensorTime.length;
282 }
283
284 return -1;
285}
const KoID FadeId("fade", ki18nc("Context: dynamic sensors", "Fade"))
generate a number that increase every time you call it (e.g. per dab)
const KoID PerspectiveId("perspective", ki18nc("Context: dynamic sensors", "Perspective"))
< tilt elevation is 90 when stylus is perpendicular to tablet and 0 when it's parallel to tablet
const KoID XTiltId("xtilt", ki18nc("Context: dynamic sensors", "X-Tilt"))
number depending on X-tilt
const KoID PressureInId("pressurein", ki18nc("Context: dynamic sensors", "PressureIn"))
number depending on the pressure
const KoID TiltElevationId("declination", ki18nc("Context: dynamic sensors", "Tilt elevation"))
< number depending on the X and Y tilt, tilt direction is 0 when stylus nib points to you and changes...
const KoID FuzzyPerStrokeId("fuzzystroke", ki18nc("Context: dynamic sensors", "Fuzzy Stroke"))
generate a random number
const KoID PressureId("pressure", ki18nc("Context: dynamic sensors", "Pressure"))
number depending on the pressure
const KoID YTiltId("ytilt", ki18nc("Context: dynamic sensors", "Y-Tilt"))
number depending on Y-tilt
const KoID TangentialPressureId("tangentialpressure", ki18nc("Context: dynamic sensors", "Tangential pressure"))
the wheel on an airbrush device
const KoID RotationId("rotation", ki18nc("Context: dynamic sensors", "Rotation"))
rotation coming from the device
const KoID TiltDirectionId("ascension", ki18nc("Context: dynamic sensors", "Tilt direction"))
const KoID DistanceId("distance", ki18nc("Context: dynamic sensors", "Distance"))
generate a number that increase with distance
const KoID TimeId("time", ki18nc("Context: dynamic sensors", "Time"))
generate a number that increase with time
const KoID FuzzyPerDabId("fuzzy", ki18nc("Context: dynamic sensors", "Fuzzy Dab"))
generate a random number
const KoID SpeedId("speed", ki18nc("Context: dynamic sensors", "Speed"))
generate a number depending on the speed of the cursor
KisKritaSensorPack(Checkability checkability)
int calcActiveSensorLength(const QString &activeSensorId) const override
std::vector< const KisSensorData * > constSensors() const override
bool read(KisCurveOptionDataCommon &data, const KisPropertiesConfiguration *setting) const override
const KisKritaSensorData & constSensorsStruct() const
std::vector< KisSensorData * > sensors() override
KisKritaSensorData & sensorsStruct()
void write(const KisCurveOptionDataCommon &data, KisPropertiesConfiguration *setting) const override
bool compare(const KisSensorPackInterface *rhs) const override
KisKritaSensorData m_data
Checkability m_checkability
KisSensorPackInterface * clone() const override
QString id() const
Definition KoID.cpp:63
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
const QString DEFAULT_CURVE_STRING
std::vector< SensorData * > sensors(Data *data)
typename copy_const< Src, Dst >::type copy_const_t
std::vector< const KisSensorData * > sensors() const
ValueFixUpReadCallback valueFixUpReadCallback
ValueFixUpWriteCallback valueFixUpWriteCallback
KisSensorWithLengthData sensorTime
KisSensorWithLengthData sensorDistance
KisSensorData sensorPressure
KisSensorWithLengthData sensorFade
QString getString(const QString &name, const QString &def=QString()) const
virtual void setProperty(const QString &name, const QVariant &value)
bool getBool(const QString &name, bool def=false) const
int getInt(const QString &name, int def=0) const
double getDouble(const QString &name, double def=0.0) const
virtual void write(QDomDocument &doc, QDomElement &e) const
virtual void reset()
virtual void read(const QDomElement &e)