Skip to content

Commit c620b36

Browse files
committed
Implement pen_setPenColorToColor block
1 parent 47abf0c commit c620b36

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

src/blocks/penblocks.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <scratchcpp/compiler.h>
44
#include <scratchcpp/sprite.h>
5+
#include <scratchcpp/color.h>
56

67
#include "penblocks.h"
78
#include "penlayer.h"
@@ -25,10 +26,12 @@ void PenBlocks::registerBlocks(IEngine *engine)
2526
engine->addCompileFunction(this, "pen_clear", &compileClear);
2627
engine->addCompileFunction(this, "pen_penDown", &compilePenDown);
2728
engine->addCompileFunction(this, "pen_penUp", &compilePenUp);
29+
engine->addCompileFunction(this, "pen_setPenColorToColor", &compileSetPenColorToColor);
2830
engine->addCompileFunction(this, "pen_changePenSizeBy", &compileChangePenSizeBy);
2931
engine->addCompileFunction(this, "pen_setPenSizeTo", &compileSetPenSizeTo);
3032

3133
// Inputs
34+
engine->addInput(this, "COLOR", COLOR);
3235
engine->addInput(this, "SIZE", SIZE);
3336
}
3437

@@ -47,6 +50,12 @@ void PenBlocks::compilePenUp(Compiler *compiler)
4750
compiler->addFunctionCall(&penUp);
4851
}
4952

53+
void PenBlocks::compileSetPenColorToColor(libscratchcpp::Compiler *compiler)
54+
{
55+
compiler->addInput(COLOR);
56+
compiler->addFunctionCall(&setPenColorToColor);
57+
}
58+
5059
void PenBlocks::compileChangePenSizeBy(libscratchcpp::Compiler *compiler)
5160
{
5261
compiler->addInput(SIZE);
@@ -111,6 +120,41 @@ unsigned int PenBlocks::setPenSizeTo(libscratchcpp::VirtualMachine *vm)
111120
return 1;
112121
}
113122

123+
unsigned int PenBlocks::setPenColorToColor(libscratchcpp::VirtualMachine *vm)
124+
{
125+
SpriteModel *model = getSpriteModel(vm);
126+
127+
if (model) {
128+
const Value *value = vm->getInput(0, 1);
129+
std::string stringValue;
130+
PenAttributes &attributes = model->penAttributes();
131+
132+
if (value->isString())
133+
stringValue = value->toString();
134+
135+
if (!stringValue.empty() && stringValue[0] == '#') {
136+
bool valid = false;
137+
138+
if (stringValue.size() <= 7) // #RRGGBB
139+
{
140+
attributes.color = QColor::fromString(stringValue);
141+
valid = attributes.color.isValid();
142+
}
143+
144+
if (!valid)
145+
attributes.color = QColor(0, 0, 0);
146+
147+
} else {
148+
attributes.color = QColor::fromRgba(static_cast<QRgb>(value->toLong()));
149+
150+
if (attributes.color.alpha() == 0)
151+
attributes.color.setAlpha(255);
152+
}
153+
}
154+
155+
return 1;
156+
}
157+
114158
SpriteModel *PenBlocks::getSpriteModel(libscratchcpp::VirtualMachine *vm)
115159
{
116160
Target *target = vm->target();

src/blocks/penblocks.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class PenBlocks : public libscratchcpp::IBlockSection
1414
public:
1515
enum Inputs
1616
{
17+
COLOR,
1718
SIZE
1819
};
1920

@@ -24,12 +25,14 @@ class PenBlocks : public libscratchcpp::IBlockSection
2425
static void compileClear(libscratchcpp::Compiler *compiler);
2526
static void compilePenDown(libscratchcpp::Compiler *compiler);
2627
static void compilePenUp(libscratchcpp::Compiler *compiler);
28+
static void compileSetPenColorToColor(libscratchcpp::Compiler *compiler);
2729
static void compileChangePenSizeBy(libscratchcpp::Compiler *compiler);
2830
static void compileSetPenSizeTo(libscratchcpp::Compiler *compiler);
2931

3032
static unsigned int clear(libscratchcpp::VirtualMachine *vm);
3133
static unsigned int penDown(libscratchcpp::VirtualMachine *vm);
3234
static unsigned int penUp(libscratchcpp::VirtualMachine *vm);
35+
static unsigned int setPenColorToColor(libscratchcpp::VirtualMachine *vm);
3336
static unsigned int changePenSizeBy(libscratchcpp::VirtualMachine *vm);
3437
static unsigned int setPenSizeTo(libscratchcpp::VirtualMachine *vm);
3538

test/blocks/pen_blocks_test.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,12 @@ TEST_F(PenBlocksTest, RegisterBlocks)
6464
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_clear", &PenBlocks::compileClear));
6565
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_penDown", &PenBlocks::compilePenDown));
6666
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_penUp", &PenBlocks::compilePenUp));
67+
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_setPenColorToColor", &PenBlocks::compileSetPenColorToColor));
6768
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_changePenSizeBy", &PenBlocks::compileChangePenSizeBy));
6869
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_setPenSizeTo", &PenBlocks::compileSetPenSizeTo));
6970

7071
// Inputs
72+
EXPECT_CALL(m_engineMock, addInput(m_section.get(), "COLOR", PenBlocks::COLOR));
7173
EXPECT_CALL(m_engineMock, addInput(m_section.get(), "SIZE", PenBlocks::SIZE));
7274

7375
m_section->registerBlocks(&m_engineMock);
@@ -193,6 +195,99 @@ TEST_F(PenBlocksTest, PenUpImpl)
193195
ASSERT_FALSE(model.penDown());
194196
}
195197

198+
TEST_F(PenBlocksTest, SetPenColorToColor)
199+
{
200+
Compiler compiler(&m_engineMock);
201+
202+
// set pen color to ("#AABBCC")
203+
auto block1 = std::make_shared<Block>("a", "pen_setPenColorToColor");
204+
addValueInput(block1, "COLOR", PenBlocks::COLOR, "#AABBCC");
205+
206+
// set pen color to (null block)
207+
auto block2 = std::make_shared<Block>("b", "pen_setPenColorToColor");
208+
addObscuredInput(block2, "COLOR", PenBlocks::COLOR, createNullBlock("c"));
209+
210+
compiler.init();
211+
212+
EXPECT_CALL(m_engineMock, functionIndex(&PenBlocks::setPenColorToColor)).WillOnce(Return(2));
213+
compiler.setBlock(block1);
214+
PenBlocks::compileSetPenColorToColor(&compiler);
215+
216+
EXPECT_CALL(m_engineMock, functionIndex(&PenBlocks::setPenColorToColor)).WillOnce(Return(2));
217+
compiler.setBlock(block2);
218+
PenBlocks::compileSetPenColorToColor(&compiler);
219+
220+
compiler.end();
221+
222+
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 }));
223+
ASSERT_EQ(compiler.constValues().size(), 1);
224+
ASSERT_EQ(compiler.constValues()[0].toString(), "#AABBCC");
225+
ASSERT_TRUE(compiler.variables().empty());
226+
ASSERT_TRUE(compiler.lists().empty());
227+
}
228+
229+
TEST_F(PenBlocksTest, SetPenColorToColorImpl)
230+
{
231+
static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_HALT };
232+
static unsigned int bytecode2[] = { vm::OP_START, vm::OP_CONST, 1, vm::OP_EXEC, 0, vm::OP_HALT };
233+
static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_HALT };
234+
static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 0, vm::OP_HALT };
235+
static unsigned int bytecode5[] = { vm::OP_START, vm::OP_CONST, 4, vm::OP_EXEC, 0, vm::OP_HALT };
236+
static unsigned int bytecode6[] = { vm::OP_START, vm::OP_CONST, 5, vm::OP_EXEC, 0, vm::OP_HALT };
237+
static unsigned int bytecode7[] = { vm::OP_START, vm::OP_CONST, 6, vm::OP_EXEC, 0, vm::OP_HALT };
238+
static BlockFunc functions[] = { &PenBlocks::setPenColorToColor };
239+
static Value constValues[] = { "#AABbCC", "#03F", "#FFGFFF", "#AABBCCDD", "FFFFFF", 1228097602, 255 };
240+
241+
SpriteModel model;
242+
Sprite sprite;
243+
sprite.setInterface(&model);
244+
245+
VirtualMachine vm(&sprite, &m_engineMock, nullptr);
246+
vm.setBytecode(bytecode1);
247+
vm.setFunctions(functions);
248+
vm.setConstValues(constValues);
249+
250+
vm.run();
251+
ASSERT_EQ(vm.registerCount(), 0);
252+
ASSERT_EQ(model.penAttributes().color, QColor(170, 187, 204));
253+
254+
vm.reset();
255+
vm.setBytecode(bytecode2);
256+
vm.run();
257+
ASSERT_EQ(vm.registerCount(), 0);
258+
ASSERT_EQ(model.penAttributes().color, QColor(0, 51, 255));
259+
260+
vm.reset();
261+
vm.setBytecode(bytecode3);
262+
vm.run();
263+
ASSERT_EQ(vm.registerCount(), 0);
264+
ASSERT_EQ(model.penAttributes().color, QColor(0, 0, 0));
265+
266+
vm.reset();
267+
vm.setBytecode(bytecode4);
268+
vm.run();
269+
ASSERT_EQ(vm.registerCount(), 0);
270+
ASSERT_EQ(model.penAttributes().color, QColor(0, 0, 0));
271+
272+
vm.reset();
273+
vm.setBytecode(bytecode5);
274+
vm.run();
275+
ASSERT_EQ(vm.registerCount(), 0);
276+
ASSERT_EQ(model.penAttributes().color, QColor(0, 0, 0));
277+
278+
vm.reset();
279+
vm.setBytecode(bytecode6);
280+
vm.run();
281+
ASSERT_EQ(vm.registerCount(), 0);
282+
ASSERT_EQ(model.penAttributes().color, QColor::fromRgba(1228097602));
283+
284+
vm.reset();
285+
vm.setBytecode(bytecode7);
286+
vm.run();
287+
ASSERT_EQ(vm.registerCount(), 0);
288+
ASSERT_EQ(model.penAttributes().color, QColor::fromRgb(255));
289+
}
290+
196291
TEST_F(PenBlocksTest, ChangePenSizeBy)
197292
{
198293
Compiler compiler(&m_engineMock);

0 commit comments

Comments
 (0)