Skip to content

Commit 4b48bcc

Browse files
committed
Implement pen_changePenShadeBy block
1 parent 8d5a64d commit 4b48bcc

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

src/blocks/penblocks.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ void PenBlocks::registerBlocks(IEngine *engine)
2929
engine->addCompileFunction(this, "pen_setPenColorToColor", &compileSetPenColorToColor);
3030
engine->addCompileFunction(this, "pen_changePenSizeBy", &compileChangePenSizeBy);
3131
engine->addCompileFunction(this, "pen_setPenSizeTo", &compileSetPenSizeTo);
32+
engine->addCompileFunction(this, "pen_changePenShadeBy", &compileChangePenShadeBy);
3233
engine->addCompileFunction(this, "pen_changePenHueBy", &compileChangePenHueBy);
3334
engine->addCompileFunction(this, "pen_setPenHueToNumber", &compileSetPenHueToNumber);
3435

3536
// Inputs
3637
engine->addInput(this, "COLOR", COLOR);
3738
engine->addInput(this, "SIZE", SIZE);
39+
engine->addInput(this, "SHADE", SHADE);
3840
engine->addInput(this, "HUE", HUE);
3941
}
4042

@@ -71,6 +73,12 @@ void PenBlocks::compileSetPenSizeTo(libscratchcpp::Compiler *compiler)
7173
compiler->addFunctionCall(&setPenSizeTo);
7274
}
7375

76+
void PenBlocks::compileChangePenShadeBy(Compiler *compiler)
77+
{
78+
compiler->addInput(SHADE);
79+
compiler->addFunctionCall(&changePenShadeBy);
80+
}
81+
7482
void PenBlocks::compileChangePenHueBy(libscratchcpp::Compiler *compiler)
7583
{
7684
compiler->addInput(HUE);
@@ -135,6 +143,18 @@ unsigned int PenBlocks::setPenSizeTo(libscratchcpp::VirtualMachine *vm)
135143
return 1;
136144
}
137145

146+
unsigned int PenBlocks::changePenShadeBy(libscratchcpp::VirtualMachine *vm)
147+
{
148+
SpriteModel *model = getSpriteModel(vm);
149+
150+
if (model) {
151+
PenState &penState = model->penState();
152+
setPenShade(penState.shade + vm->getInput(0, 1)->toDouble(), penState);
153+
}
154+
155+
return 1;
156+
}
157+
138158
unsigned int PenBlocks::changePenHueBy(libscratchcpp::VirtualMachine *vm)
139159
{
140160
SpriteModel *model = getSpriteModel(vm);
@@ -234,6 +254,21 @@ void PenBlocks::setOrChangeColorParam(ColorParam param, double value, PenState &
234254
penState.updateColor();
235255
}
236256

257+
void PenBlocks::setPenShade(int shade, PenState &penState)
258+
{
259+
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/extensions/scratch3_pen/index.js#L718-L730
260+
// Wrap clamp the new shade value the way Scratch 2 did
261+
shade = shade % 200;
262+
263+
if (shade < 0)
264+
shade += 200;
265+
266+
// And store the shade that was used to compute this new color for later use
267+
penState.shade = shade;
268+
269+
legacyUpdatePenColor(penState);
270+
}
271+
237272
void PenBlocks::legacyUpdatePenColor(PenState &penState)
238273
{
239274
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/extensions/scratch3_pen/index.js#L750-L767

src/blocks/penblocks.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class PenBlocks : public libscratchcpp::IBlockSection
1818
{
1919
COLOR,
2020
SIZE,
21+
SHADE,
2122
HUE
2223
};
2324

@@ -31,6 +32,7 @@ class PenBlocks : public libscratchcpp::IBlockSection
3132
static void compileSetPenColorToColor(libscratchcpp::Compiler *compiler);
3233
static void compileChangePenSizeBy(libscratchcpp::Compiler *compiler);
3334
static void compileSetPenSizeTo(libscratchcpp::Compiler *compiler);
35+
static void compileChangePenShadeBy(libscratchcpp::Compiler *compiler);
3436
static void compileChangePenHueBy(libscratchcpp::Compiler *compiler);
3537
static void compileSetPenHueToNumber(libscratchcpp::Compiler *compiler);
3638

@@ -40,6 +42,7 @@ class PenBlocks : public libscratchcpp::IBlockSection
4042
static unsigned int setPenColorToColor(libscratchcpp::VirtualMachine *vm);
4143
static unsigned int changePenSizeBy(libscratchcpp::VirtualMachine *vm);
4244
static unsigned int setPenSizeTo(libscratchcpp::VirtualMachine *vm);
45+
static unsigned int changePenShadeBy(libscratchcpp::VirtualMachine *vm);
4346
static unsigned int changePenHueBy(libscratchcpp::VirtualMachine *vm);
4447
static unsigned int setPenHueToNumber(libscratchcpp::VirtualMachine *vm);
4548

@@ -51,6 +54,7 @@ class PenBlocks : public libscratchcpp::IBlockSection
5154

5255
static SpriteModel *getSpriteModel(libscratchcpp::VirtualMachine *vm);
5356
static void setOrChangeColorParam(ColorParam param, double value, PenState &penState, bool change);
57+
static void setPenShade(int shade, PenState &penState);
5458
static void legacyUpdatePenColor(PenState &penState);
5559
static double wrapClamp(double n, double min, double max);
5660
static QRgb mixRgb(QRgb rgb0, QRgb rgb1, double fraction1);

test/blocks/pen_blocks_test.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,14 @@ TEST_F(PenBlocksTest, RegisterBlocks)
6767
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_setPenColorToColor", &PenBlocks::compileSetPenColorToColor));
6868
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_changePenSizeBy", &PenBlocks::compileChangePenSizeBy));
6969
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_setPenSizeTo", &PenBlocks::compileSetPenSizeTo));
70+
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_changePenShadeBy", &PenBlocks::compileChangePenShadeBy));
7071
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_changePenHueBy", &PenBlocks::compileChangePenHueBy));
7172
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_setPenHueToNumber", &PenBlocks::compileSetPenHueToNumber));
7273

7374
// Inputs
7475
EXPECT_CALL(m_engineMock, addInput(m_section.get(), "COLOR", PenBlocks::COLOR));
7576
EXPECT_CALL(m_engineMock, addInput(m_section.get(), "SIZE", PenBlocks::SIZE));
77+
EXPECT_CALL(m_engineMock, addInput(m_section.get(), "SHADE", PenBlocks::SHADE));
7678
EXPECT_CALL(m_engineMock, addInput(m_section.get(), "HUE", PenBlocks::HUE));
7779

7880
m_section->registerBlocks(&m_engineMock);
@@ -429,6 +431,80 @@ TEST_F(PenBlocksTest, SetPenSizeToImpl)
429431
ASSERT_EQ(model.penAttributes().diameter, 1200);
430432
}
431433

434+
TEST_F(PenBlocksTest, ChangePenShadeBy)
435+
{
436+
Compiler compiler(&m_engineMock);
437+
438+
// change pen shade by (4.5)
439+
auto block1 = std::make_shared<Block>("a", "pen_changePenShadeBy");
440+
addValueInput(block1, "SHADE", PenBlocks::SHADE, 4.5);
441+
442+
// change pen shade by (null block)
443+
auto block2 = std::make_shared<Block>("b", "pen_changePenShadeBy");
444+
addObscuredInput(block2, "SHADE", PenBlocks::SHADE, createNullBlock("c"));
445+
446+
compiler.init();
447+
448+
EXPECT_CALL(m_engineMock, functionIndex(&PenBlocks::changePenShadeBy)).WillOnce(Return(2));
449+
compiler.setBlock(block1);
450+
PenBlocks::compileChangePenShadeBy(&compiler);
451+
452+
EXPECT_CALL(m_engineMock, functionIndex(&PenBlocks::changePenShadeBy)).WillOnce(Return(2));
453+
compiler.setBlock(block2);
454+
PenBlocks::compileChangePenShadeBy(&compiler);
455+
456+
compiler.end();
457+
458+
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 2, vm::OP_NULL, vm::OP_EXEC, 2, vm::OP_HALT }));
459+
ASSERT_EQ(compiler.constValues().size(), 1);
460+
ASSERT_EQ(compiler.constValues()[0].toDouble(), 4.5);
461+
ASSERT_TRUE(compiler.variables().empty());
462+
ASSERT_TRUE(compiler.lists().empty());
463+
}
464+
465+
TEST_F(PenBlocksTest, ChangePenShadeByImpl)
466+
{
467+
static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_HALT };
468+
static unsigned int bytecode2[] = { vm::OP_START, vm::OP_CONST, 1, vm::OP_EXEC, 0, vm::OP_HALT };
469+
static BlockFunc functions[] = { &PenBlocks::changePenShadeBy };
470+
static Value constValues[] = { 134.09, -124.45 };
471+
472+
SpriteModel model;
473+
model.penState().transparency = 100 * (1 - 150 / 255.0);
474+
Sprite sprite;
475+
sprite.setInterface(&model);
476+
477+
VirtualMachine vm(&sprite, &m_engineMock, nullptr);
478+
vm.setBytecode(bytecode1);
479+
vm.setFunctions(functions);
480+
vm.setConstValues(constValues);
481+
482+
vm.run();
483+
ASSERT_EQ(vm.registerCount(), 0);
484+
ASSERT_EQ(model.penAttributes().color, QColor::fromHsv(240, 255, 110, 150));
485+
486+
vm.reset();
487+
vm.run();
488+
ASSERT_EQ(vm.registerCount(), 0);
489+
ASSERT_EQ(model.penAttributes().color, QColor::fromHsv(240, 119, 255, 150));
490+
491+
vm.reset();
492+
vm.run();
493+
ASSERT_EQ(vm.registerCount(), 0);
494+
ASSERT_EQ(model.penAttributes().color, QColor::fromHsv(240, 247, 255, 150));
495+
496+
vm.reset();
497+
vm.setBytecode(bytecode2);
498+
vm.run();
499+
ASSERT_EQ(vm.registerCount(), 0);
500+
ASSERT_EQ(model.penAttributes().color, QColor::fromHsv(240, 162, 255, 150));
501+
502+
vm.reset();
503+
vm.run();
504+
ASSERT_EQ(vm.registerCount(), 0);
505+
ASSERT_EQ(model.penAttributes().color, QColor::fromHsv(240, 255, 55, 150));
506+
}
507+
432508
TEST_F(PenBlocksTest, ChangePenHueBy)
433509
{
434510
Compiler compiler(&m_engineMock);

0 commit comments

Comments
 (0)