Skip to content

Commit 58ba361

Browse files
committed
Implement pen_stamp block
1 parent 3dc61a4 commit 58ba361

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

src/blocks/penblocks.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
#include <scratchcpp/compiler.h>
44
#include <scratchcpp/sprite.h>
5+
#include <scratchcpp/stage.h>
56
#include <scratchcpp/input.h>
67

78
#include "penblocks.h"
89
#include "penlayer.h"
910
#include "penstate.h"
1011
#include "spritemodel.h"
12+
#include "stagemodel.h"
1113

1214
using namespace scratchcpprender;
1315
using namespace libscratchcpp;
@@ -31,6 +33,7 @@ void PenBlocks::registerBlocks(IEngine *engine)
3133
{
3234
// Blocks
3335
engine->addCompileFunction(this, "pen_clear", &compileClear);
36+
engine->addCompileFunction(this, "pen_stamp", &compileStamp);
3437
engine->addCompileFunction(this, "pen_penDown", &compilePenDown);
3538
engine->addCompileFunction(this, "pen_penUp", &compilePenUp);
3639
engine->addCompileFunction(this, "pen_setPenColorToColor", &compileSetPenColorToColor);
@@ -57,6 +60,11 @@ void PenBlocks::compileClear(Compiler *compiler)
5760
compiler->addFunctionCall(&clear);
5861
}
5962

63+
void PenBlocks::compileStamp(Compiler *compiler)
64+
{
65+
compiler->addFunctionCall(&stamp);
66+
}
67+
6068
void PenBlocks::compilePenDown(Compiler *compiler)
6169
{
6270
compiler->addFunctionCall(&penDown);
@@ -179,6 +187,29 @@ unsigned int PenBlocks::clear(VirtualMachine *vm)
179187
return 0;
180188
}
181189

190+
unsigned int PenBlocks::stamp(libscratchcpp::VirtualMachine *vm)
191+
{
192+
IPenLayer *penLayer = PenLayer::getProjectPenLayer(vm->engine());
193+
194+
if (penLayer) {
195+
Target *target = vm->target();
196+
IRenderedTarget *renderedTarget = nullptr;
197+
198+
if (target->isStage()) {
199+
IStageHandler *iface = static_cast<Stage *>(target)->getInterface();
200+
renderedTarget = static_cast<StageModel *>(iface)->renderedTarget();
201+
} else {
202+
ISpriteHandler *iface = static_cast<Sprite *>(target)->getInterface();
203+
renderedTarget = static_cast<SpriteModel *>(iface)->renderedTarget();
204+
}
205+
206+
penLayer->stamp(renderedTarget);
207+
vm->engine()->requestRedraw();
208+
}
209+
210+
return 0;
211+
}
212+
182213
unsigned int PenBlocks::penDown(VirtualMachine *vm)
183214
{
184215
SpriteModel *model = getSpriteModel(vm);

src/blocks/penblocks.h

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class PenBlocks : public libscratchcpp::IBlockSection
2929
void registerBlocks(libscratchcpp::IEngine *engine) override;
3030

3131
static void compileClear(libscratchcpp::Compiler *compiler);
32+
static void compileStamp(libscratchcpp::Compiler *compiler);
3233
static void compilePenDown(libscratchcpp::Compiler *compiler);
3334
static void compilePenUp(libscratchcpp::Compiler *compiler);
3435
static void compileSetPenColorToColor(libscratchcpp::Compiler *compiler);
@@ -42,6 +43,7 @@ class PenBlocks : public libscratchcpp::IBlockSection
4243
static void compileSetPenHueToNumber(libscratchcpp::Compiler *compiler);
4344

4445
static unsigned int clear(libscratchcpp::VirtualMachine *vm);
46+
static unsigned int stamp(libscratchcpp::VirtualMachine *vm);
4547
static unsigned int penDown(libscratchcpp::VirtualMachine *vm);
4648
static unsigned int penUp(libscratchcpp::VirtualMachine *vm);
4749
static unsigned int setPenColorToColor(libscratchcpp::VirtualMachine *vm);

test/blocks/pen_blocks_test.cpp

+63
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
#include <scratchcpp/field.h>
55
#include <penlayer.h>
66
#include <spritemodel.h>
7+
#include <stagemodel.h>
78
#include <blocks/penblocks.h>
89
#include <enginemock.h>
910
#include <penlayermock.h>
11+
#include <renderedtargetmock.h>
1012

1113
#include "../common.h"
1214

@@ -92,6 +94,7 @@ TEST_F(PenBlocksTest, RegisterBlocks)
9294
{
9395
// Blocks
9496
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_clear", &PenBlocks::compileClear));
97+
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_stamp", &PenBlocks::compileStamp));
9598
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_penDown", &PenBlocks::compilePenDown));
9699
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_penUp", &PenBlocks::compilePenUp));
97100
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "pen_setPenColorToColor", &PenBlocks::compileSetPenColorToColor));
@@ -133,6 +136,66 @@ TEST_F(PenBlocksTest, Clear)
133136
ASSERT_TRUE(compiler.lists().empty());
134137
}
135138

139+
TEST_F(PenBlocksTest, Stamp)
140+
{
141+
Compiler compiler(&m_engineMock);
142+
143+
auto block = std::make_shared<Block>("a", "pen_stamp");
144+
145+
EXPECT_CALL(m_engineMock, functionIndex(&PenBlocks::stamp)).WillOnce(Return(2));
146+
compiler.init();
147+
compiler.setBlock(block);
148+
PenBlocks::compileStamp(&compiler);
149+
compiler.end();
150+
151+
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_EXEC, 2, vm::OP_HALT }));
152+
ASSERT_TRUE(compiler.constValues().empty());
153+
ASSERT_TRUE(compiler.variables().empty());
154+
ASSERT_TRUE(compiler.lists().empty());
155+
}
156+
157+
TEST_F(PenBlocksTest, StampImpl)
158+
{
159+
static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT };
160+
static BlockFunc functions[] = { &PenBlocks::stamp };
161+
162+
PenLayerMock penLayer;
163+
PenLayer::addPenLayer(&m_engineMock, &penLayer);
164+
RenderedTargetMock renderedTarget;
165+
166+
// Test sprite
167+
libscratchcpp::Sprite sprite;
168+
SpriteModel spriteModel;
169+
sprite.setInterface(&spriteModel);
170+
spriteModel.setRenderedTarget(&renderedTarget);
171+
172+
VirtualMachine vm1(&sprite, &m_engineMock, nullptr);
173+
vm1.setBytecode(bytecode);
174+
vm1.setFunctions(functions);
175+
176+
EXPECT_CALL(penLayer, stamp(&renderedTarget));
177+
EXPECT_CALL(m_engineMock, requestRedraw());
178+
vm1.run();
179+
180+
ASSERT_EQ(vm1.registerCount(), 0);
181+
182+
// Test stage
183+
libscratchcpp::Stage stage;
184+
StageModel stageModel;
185+
stage.setInterface(&stageModel);
186+
stageModel.setRenderedTarget(&renderedTarget);
187+
188+
VirtualMachine vm2(&stage, &m_engineMock, nullptr);
189+
vm2.setBytecode(bytecode);
190+
vm2.setFunctions(functions);
191+
192+
EXPECT_CALL(penLayer, stamp(&renderedTarget));
193+
EXPECT_CALL(m_engineMock, requestRedraw());
194+
vm2.run();
195+
196+
ASSERT_EQ(vm2.registerCount(), 0);
197+
}
198+
136199
TEST_F(PenBlocksTest, ClearImpl)
137200
{
138201
static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT };

0 commit comments

Comments
 (0)