@@ -134,7 +134,7 @@ unsigned int PenBlocks::changePenHueBy(libscratchcpp::VirtualMachine *vm)
134
134
135
135
if (model) {
136
136
const double colorChange = vm->getInput (0 , 1 )->toDouble () / 2 ;
137
- setOrChangeColorParam (model-> penAttributes (), ColorParam::COLOR, colorChange, true );
137
+ setOrChangeColorParam (ColorParam::COLOR, colorChange, model-> penState (), true , true );
138
138
}
139
139
140
140
return 1 ;
@@ -147,7 +147,8 @@ unsigned int PenBlocks::setPenColorToColor(libscratchcpp::VirtualMachine *vm)
147
147
if (model) {
148
148
const Value *value = vm->getInput (0 , 1 );
149
149
std::string stringValue;
150
- PenAttributes &attributes = model->penAttributes ();
150
+ PenState &penState = model->penState ();
151
+ QColor newColor;
151
152
152
153
if (value->isString ())
153
154
stringValue = value->toString ();
@@ -157,19 +158,24 @@ unsigned int PenBlocks::setPenColorToColor(libscratchcpp::VirtualMachine *vm)
157
158
158
159
if (stringValue.size () <= 7 ) // #RRGGBB
159
160
{
160
- attributes. color = QColor::fromString (stringValue);
161
- valid = attributes. color .isValid ();
161
+ newColor = QColor::fromString (stringValue);
162
+ valid = newColor .isValid ();
162
163
}
163
164
164
165
if (!valid)
165
- attributes. color = QColor ( 0 , 0 , 0 ) ;
166
+ newColor = Qt::black ;
166
167
167
168
} else {
168
- attributes. color = QColor::fromRgba (static_cast <QRgb>(value->toLong ()));
169
+ newColor = QColor::fromRgba (static_cast <QRgb>(value->toLong ()));
169
170
170
- if (attributes. color .alpha () == 0 )
171
- attributes. color .setAlpha (255 );
171
+ if (newColor .alpha () == 0 )
172
+ newColor .setAlpha (255 );
172
173
}
174
+
175
+ penState.setColor (newColor);
176
+
177
+ // Set the legacy "shade" value the same way Scratch 2 did.
178
+ penState.shade = penState.brightness / 2 ;
173
179
}
174
180
175
181
return 1 ;
@@ -187,22 +193,31 @@ SpriteModel *PenBlocks::getSpriteModel(libscratchcpp::VirtualMachine *vm)
187
193
return model;
188
194
}
189
195
190
- void PenBlocks::setOrChangeColorParam (PenAttributes &penAttributes, ColorParam param, double value, bool change)
196
+ void PenBlocks::setOrChangeColorParam (ColorParam param, double value, PenState &penState, bool change, bool legacy )
191
197
{
192
- PenState penState;
193
- penState.setColor (penAttributes.color );
194
-
195
198
switch (param) {
196
199
case ColorParam::COLOR:
197
200
penState.color = wrapClamp (value + (change ? penState.color : 0 ), 0 , 100 );
198
201
break ;
199
202
}
200
203
201
- const int h = std::round (std::fmod (penState.color * 360 / 100 , 360.0 ));
202
- const int s = std::round (penState.saturation * 2.55 );
203
- const int v = std::round (penState.brightness * 2.55 );
204
- const int a = std::round ((100 - penState.transparency ) * 2.55 );
205
- penAttributes.color = QColor::fromHsv (h, s, v, a);
204
+ penState.updateColor ();
205
+
206
+ if (legacy) {
207
+ // https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/extensions/scratch3_pen/index.js#L750-L767
208
+ // Create the new color in RGB using the scratch 2 "shade" model
209
+ QColor rgb = penState.penAttributes .color .toRgb ();
210
+ const double shade = (penState.shade > 100 ) ? 200 - penState.shade : penState.shade ;
211
+
212
+ if (shade < 50 )
213
+ rgb = mixRgb (QColor (Qt::black), rgb, (10 + shade) / 60 );
214
+ else
215
+ rgb = mixRgb (rgb, QColor (Qt::white), (shade - 50 ) / 60 );
216
+
217
+ // Update the pen state according to new color
218
+ const QColor hsv = rgb.toHsv ();
219
+ penState.setColor (hsv);
220
+ }
206
221
}
207
222
208
223
double PenBlocks::wrapClamp (double n, double min, double max)
@@ -211,3 +226,15 @@ double PenBlocks::wrapClamp(double n, double min, double max)
211
226
const double range = max - min + 1 ;
212
227
return n - (std::floor ((n - min) / range) * range);
213
228
}
229
+
230
+ QColor PenBlocks::mixRgb (const QColor &rgb0, const QColor &rgb1, double fraction1)
231
+ {
232
+ // https://github.com/scratchfoundation/scratch-vm/blob/a4f095db5e03e072ba222fe721eeeb543c9b9c15/src/util/color.js#L192-L201
233
+ if (fraction1 <= 0 )
234
+ return rgb0;
235
+ if (fraction1 >= 1 )
236
+ return rgb1;
237
+
238
+ const double fraction0 = 1 - fraction1;
239
+ return QColor ((fraction0 * rgb0.red ()) + (fraction1 * rgb1.red ()), (fraction0 * rgb0.green ()) + (fraction1 * rgb1.green ()), (fraction0 * rgb0.blue ()) + (fraction1 * rgb1.blue ()));
240
+ }
0 commit comments