Skip to content

Commit 7efdd13

Browse files
committed
Implement pen_changePenSizeBy block
1 parent 544f4d3 commit 7efdd13

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed

src/blocks/penblocks.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
using namespace scratchcpprender;
2020
using namespace libscratchcpp;
2121

22+
// Pen size range: https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/extensions/scratch3_pen/index.js#L100-L102
23+
static const double PEN_SIZE_MIN = 1;
24+
static const double PEN_SIZE_MAX = 1200;
25+
2226
static const double COLOR_PARAM_MIN = 0;
2327
static const double COLOR_PARAM_MAX = 100;
2428

@@ -82,6 +86,7 @@ void PenBlocks::registerBlocks(IEngine *engine)
8286
engine->addCompileFunction(this, "pen_setPenColorToColor", &compileSetPenColorToColor);
8387
engine->addCompileFunction(this, "pen_changePenColorParamBy", &compileChangePenColorParamBy);
8488
engine->addCompileFunction(this, "pen_setPenColorParamTo", &compileSetPenColorParamTo);
89+
engine->addCompileFunction(this, "pen_changePenSizeBy", &compileChangePenSizeBy);
8590
}
8691

8792
CompilerValue *PenBlocks::compileClear(Compiler *compiler)
@@ -178,6 +183,13 @@ CompilerValue *PenBlocks::compileSetPenColorParamTo(Compiler *compiler)
178183
return nullptr;
179184
}
180185

186+
CompilerValue *PenBlocks::compileChangePenSizeBy(Compiler *compiler)
187+
{
188+
CompilerValue *size = compiler->addInput("SIZE");
189+
compiler->addTargetFunctionCall("pen_changePenSizeBy", Compiler::StaticType::Void, { Compiler::StaticType::Number }, { size });
190+
return nullptr;
191+
}
192+
181193
static TargetModel *getTargetModel(Target *target)
182194
{
183195
if (target->isStage()) {
@@ -305,3 +317,9 @@ BLOCK_EXPORT void pen_set_or_change_color_param(Target *target, const StringPtr
305317
else if (string_compare_case_sensitive(param, &TRANSPARENCY_PARAM) == 0)
306318
pen_set_or_change_transparency(target, value, change);
307319
}
320+
321+
BLOCK_EXPORT void pen_changePenSizeBy(Target *target, double value)
322+
{
323+
PenAttributes &penAttributes = getTargetModel(target)->penAttributes();
324+
penAttributes.diameter = std::clamp(penAttributes.diameter + value, PEN_SIZE_MIN, PEN_SIZE_MAX);
325+
}

src/blocks/penblocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class PenBlocks : public libscratchcpp::IExtension
2121
static void compileSetOrChangePenColorParam(libscratchcpp::Compiler *compiler, bool change);
2222
static libscratchcpp::CompilerValue *compileChangePenColorParamBy(libscratchcpp::Compiler *compiler);
2323
static libscratchcpp::CompilerValue *compileSetPenColorParamTo(libscratchcpp::Compiler *compiler);
24+
static libscratchcpp::CompilerValue *compileChangePenSizeBy(libscratchcpp::Compiler *compiler);
2425
};
2526

2627
} // namespace scratchcpprender

test/blocks/pen_blocks_test.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,3 +1952,128 @@ TEST_F(PenBlocksTest, SetPenColorParamTo_Stage)
19521952
EXPECT_EQ(model.penAttributes().color.blue(), 149);
19531953
EXPECT_EQ(model.penAttributes().color.alpha(), 255);
19541954
}
1955+
1956+
TEST_F(PenBlocksTest, ChangePenSizeBy)
1957+
{
1958+
auto sprite = std::make_shared<Sprite>();
1959+
sprite->setEngine(&m_engineMock);
1960+
1961+
RenderedTarget renderedTarget;
1962+
SpriteModel model;
1963+
model.init(sprite.get());
1964+
model.setRenderedTarget(&renderedTarget);
1965+
sprite->setInterface(&model);
1966+
1967+
ScriptBuilder builder(m_extension.get(), m_engine, sprite);
1968+
builder.addBlock("pen_changePenSizeBy");
1969+
builder.addValueInput("SIZE", 511.5);
1970+
1971+
model.penAttributes().diameter = 2.3;
1972+
1973+
auto thread = buildScript(builder, sprite.get());
1974+
1975+
EXPECT_CALL(m_engineMock, requestRedraw).Times(0);
1976+
1977+
thread->run();
1978+
ASSERT_EQ(model.penAttributes().diameter, 513.8);
1979+
}
1980+
1981+
TEST_F(PenBlocksTest, ChangePenSizeBy_Negative)
1982+
{
1983+
auto sprite = std::make_shared<Sprite>();
1984+
sprite->setEngine(&m_engineMock);
1985+
1986+
RenderedTarget renderedTarget;
1987+
SpriteModel model;
1988+
model.init(sprite.get());
1989+
model.setRenderedTarget(&renderedTarget);
1990+
sprite->setInterface(&model);
1991+
1992+
ScriptBuilder builder(m_extension.get(), m_engine, sprite);
1993+
builder.addBlock("pen_changePenSizeBy");
1994+
builder.addValueInput("SIZE", -0.5);
1995+
1996+
model.penAttributes().diameter = 2.3;
1997+
1998+
auto thread = buildScript(builder, sprite.get());
1999+
2000+
EXPECT_CALL(m_engineMock, requestRedraw).Times(0);
2001+
2002+
thread->run();
2003+
ASSERT_EQ(std::round(model.penAttributes().diameter * 100) / 100, 1.8);
2004+
}
2005+
2006+
TEST_F(PenBlocksTest, ChangePenSizeBy_AboveMaximum)
2007+
{
2008+
auto sprite = std::make_shared<Sprite>();
2009+
sprite->setEngine(&m_engineMock);
2010+
2011+
RenderedTarget renderedTarget;
2012+
SpriteModel model;
2013+
model.init(sprite.get());
2014+
model.setRenderedTarget(&renderedTarget);
2015+
sprite->setInterface(&model);
2016+
2017+
ScriptBuilder builder(m_extension.get(), m_engine, sprite);
2018+
builder.addBlock("pen_changePenSizeBy");
2019+
builder.addValueInput("SIZE", 687.2);
2020+
2021+
model.penAttributes().diameter = 513.8;
2022+
2023+
auto thread = buildScript(builder, sprite.get());
2024+
2025+
EXPECT_CALL(m_engineMock, requestRedraw).Times(0);
2026+
2027+
thread->run();
2028+
ASSERT_EQ(model.penAttributes().diameter, 1200);
2029+
}
2030+
2031+
TEST_F(PenBlocksTest, ChangePenSizeBy_BelowMinimum)
2032+
{
2033+
auto sprite = std::make_shared<Sprite>();
2034+
sprite->setEngine(&m_engineMock);
2035+
2036+
RenderedTarget renderedTarget;
2037+
SpriteModel model;
2038+
model.init(sprite.get());
2039+
model.setRenderedTarget(&renderedTarget);
2040+
sprite->setInterface(&model);
2041+
2042+
ScriptBuilder builder(m_extension.get(), m_engine, sprite);
2043+
builder.addBlock("pen_changePenSizeBy");
2044+
builder.addValueInput("SIZE", -13);
2045+
2046+
model.penAttributes().diameter = 12.5;
2047+
2048+
auto thread = buildScript(builder, sprite.get());
2049+
2050+
EXPECT_CALL(m_engineMock, requestRedraw).Times(0);
2051+
2052+
thread->run();
2053+
ASSERT_EQ(model.penAttributes().diameter, 1);
2054+
}
2055+
2056+
TEST_F(PenBlocksTest, ChangePenSizeBy_Stage)
2057+
{
2058+
auto stage = std::make_shared<Stage>();
2059+
stage->setEngine(&m_engineMock);
2060+
2061+
RenderedTarget renderedTarget;
2062+
StageModel model;
2063+
model.init(stage.get());
2064+
model.setRenderedTarget(&renderedTarget);
2065+
stage->setInterface(&model);
2066+
2067+
ScriptBuilder builder(m_extension.get(), m_engine, stage);
2068+
builder.addBlock("pen_changePenSizeBy");
2069+
builder.addValueInput("SIZE", 511.5);
2070+
2071+
model.penAttributes().diameter = 2.3;
2072+
2073+
auto thread = buildScript(builder, stage.get());
2074+
2075+
EXPECT_CALL(m_engineMock, requestRedraw).Times(0);
2076+
2077+
thread->run();
2078+
ASSERT_EQ(model.penAttributes().diameter, 513.8);
2079+
}

0 commit comments

Comments
 (0)