Skip to content

Commit bb7a80a

Browse files
authored
Merge pull request #321 from scratchcpp/layer_blocks
Implement layer blocks
2 parents 029426f + 8cfa0cf commit bb7a80a

File tree

5 files changed

+246
-3
lines changed

5 files changed

+246
-3
lines changed

src/blocks/looksblocks.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ void LooksBlocks::registerBlocks(IEngine *engine)
3737
engine->addCompileFunction(this, "looks_switchbackdropto", &compileSwitchBackdropTo);
3838
engine->addCompileFunction(this, "looks_switchbackdroptoandwait", &compileSwitchBackdropToAndWait);
3939
engine->addCompileFunction(this, "looks_nextbackdrop", &compileNextBackdrop);
40+
engine->addCompileFunction(this, "looks_gotofrontback", &compileGoToFrontBack);
41+
engine->addCompileFunction(this, "looks_goforwardbackwardlayers", &compileGoForwardBackwardLayers);
4042
engine->addCompileFunction(this, "looks_costumenumbername", &compileCostumeNumberName);
4143
engine->addCompileFunction(this, "looks_backdropnumbername", &compileBackdropNumberName);
4244

@@ -50,6 +52,8 @@ void LooksBlocks::registerBlocks(IEngine *engine)
5052
// Fields
5153
engine->addField(this, "NUMBER_NAME", NUMBER_NAME);
5254
engine->addField(this, "EFFECT", EFFECT);
55+
engine->addField(this, "FRONT_BACK", FRONT_BACK);
56+
engine->addField(this, "FORWARD_BACKWARD", FORWARD_BACKWARD);
5357

5458
// Field values
5559
engine->addFieldValue(this, "number", Number);
@@ -61,6 +65,10 @@ void LooksBlocks::registerBlocks(IEngine *engine)
6165
engine->addFieldValue(this, "MOSAIC", MosaicEffect);
6266
engine->addFieldValue(this, "BRIGHTNESS", BrightnessEffect);
6367
engine->addFieldValue(this, "GHOST", GhostEffect);
68+
engine->addFieldValue(this, "front", Front);
69+
engine->addFieldValue(this, "back", Back);
70+
engine->addFieldValue(this, "forward", Forward);
71+
engine->addFieldValue(this, "backward", Backward);
6472
}
6573

6674
void LooksBlocks::compileShow(Compiler *compiler)
@@ -388,6 +396,38 @@ void LooksBlocks::compileNextBackdrop(Compiler *compiler)
388396
compiler->addFunctionCall(&nextBackdrop);
389397
}
390398

399+
void LooksBlocks::compileGoToFrontBack(Compiler *compiler)
400+
{
401+
int option = compiler->field(FRONT_BACK)->specialValueId();
402+
403+
switch (option) {
404+
case Front:
405+
compiler->addFunctionCall(&goToFront);
406+
break;
407+
408+
case Back:
409+
compiler->addFunctionCall(&goToBack);
410+
break;
411+
}
412+
}
413+
414+
void LooksBlocks::compileGoForwardBackwardLayers(Compiler *compiler)
415+
{
416+
int option = compiler->field(FORWARD_BACKWARD)->specialValueId();
417+
418+
switch (option) {
419+
case Forward:
420+
compiler->addInput(NUM);
421+
compiler->addFunctionCall(&goForwardLayers);
422+
break;
423+
424+
case Backward:
425+
compiler->addInput(NUM);
426+
compiler->addFunctionCall(&goBackwardLayers);
427+
break;
428+
}
429+
}
430+
391431
void LooksBlocks::compileCostumeNumberName(Compiler *compiler)
392432
{
393433
int option = compiler->field(NUMBER_NAME)->specialValueId();
@@ -861,6 +901,46 @@ unsigned int LooksBlocks::checkBackdropScripts(VirtualMachine *vm)
861901
return 0;
862902
}
863903

904+
unsigned int LooksBlocks::goToFront(VirtualMachine *vm)
905+
{
906+
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());
907+
908+
if (sprite)
909+
vm->engine()->moveSpriteToFront(sprite);
910+
911+
return 0;
912+
}
913+
914+
unsigned int LooksBlocks::goToBack(VirtualMachine *vm)
915+
{
916+
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());
917+
918+
if (sprite)
919+
vm->engine()->moveSpriteToBack(sprite);
920+
921+
return 0;
922+
}
923+
924+
unsigned int LooksBlocks::goForwardLayers(VirtualMachine *vm)
925+
{
926+
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());
927+
928+
if (sprite)
929+
vm->engine()->moveSpriteForwardLayers(sprite, vm->getInput(0, 1)->toInt());
930+
931+
return 1;
932+
}
933+
934+
unsigned int LooksBlocks::goBackwardLayers(VirtualMachine *vm)
935+
{
936+
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());
937+
938+
if (sprite)
939+
vm->engine()->moveSpriteBackwardLayers(sprite, vm->getInput(0, 1)->toInt());
940+
941+
return 1;
942+
}
943+
864944
unsigned int LooksBlocks::costumeNumber(VirtualMachine *vm)
865945
{
866946
if (Target *target = vm->target())

src/blocks/looksblocks.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ class LooksBlocks : public IBlockSection
2424
SIZE,
2525
COSTUME,
2626
BACKDROP,
27-
VALUE
27+
VALUE,
28+
NUM
2829
};
2930

3031
enum Fields
3132
{
3233
NUMBER_NAME,
33-
EFFECT
34+
EFFECT,
35+
FRONT_BACK,
36+
FORWARD_BACKWARD
3437
};
3538

3639
enum FieldValues
@@ -43,7 +46,11 @@ class LooksBlocks : public IBlockSection
4346
PixelateEffect,
4447
MosaicEffect,
4548
BrightnessEffect,
46-
GhostEffect
49+
GhostEffect,
50+
Front,
51+
Back,
52+
Forward,
53+
Backward
4754
};
4855

4956
std::string name() const override;
@@ -63,6 +70,8 @@ class LooksBlocks : public IBlockSection
6370
static void compileSwitchBackdropTo(Compiler *compiler);
6471
static void compileSwitchBackdropToAndWait(Compiler *compiler);
6572
static void compileNextBackdrop(Compiler *compiler);
73+
static void compileGoToFrontBack(Compiler *compiler);
74+
static void compileGoForwardBackwardLayers(Compiler *compiler);
6675
static void compileCostumeNumberName(Compiler *compiler);
6776
static void compileBackdropNumberName(Compiler *compiler);
6877

@@ -117,6 +126,12 @@ class LooksBlocks : public IBlockSection
117126
static unsigned int randomBackdropAndWait(VirtualMachine *vm);
118127
static unsigned int checkBackdropScripts(VirtualMachine *vm);
119128

129+
static unsigned int goToFront(VirtualMachine *vm);
130+
static unsigned int goToBack(VirtualMachine *vm);
131+
132+
static unsigned int goForwardLayers(VirtualMachine *vm);
133+
static unsigned int goBackwardLayers(VirtualMachine *vm);
134+
120135
static unsigned int costumeNumber(VirtualMachine *vm);
121136
static unsigned int costumeName(VirtualMachine *vm);
122137
static unsigned int backdropNumber(VirtualMachine *vm);

test/blocks/looks_blocks_test.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ TEST_F(LooksBlocksTest, RegisterBlocks)
117117
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "looks_switchbackdropto", &LooksBlocks::compileSwitchBackdropTo));
118118
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "looks_switchbackdroptoandwait", &LooksBlocks::compileSwitchBackdropToAndWait));
119119
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "looks_nextbackdrop", &LooksBlocks::compileNextBackdrop));
120+
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "looks_gotofrontback", &LooksBlocks::compileGoToFrontBack));
121+
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "looks_goforwardbackwardlayers", &LooksBlocks::compileGoForwardBackwardLayers));
120122
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "looks_costumenumbername", &LooksBlocks::compileCostumeNumberName));
121123
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "looks_backdropnumbername", &LooksBlocks::compileBackdropNumberName));
122124

@@ -130,6 +132,8 @@ TEST_F(LooksBlocksTest, RegisterBlocks)
130132
// Fields
131133
EXPECT_CALL(m_engineMock, addField(m_section.get(), "NUMBER_NAME", LooksBlocks::NUMBER_NAME));
132134
EXPECT_CALL(m_engineMock, addField(m_section.get(), "EFFECT", LooksBlocks::EFFECT));
135+
EXPECT_CALL(m_engineMock, addField(m_section.get(), "FRONT_BACK", LooksBlocks::FRONT_BACK));
136+
EXPECT_CALL(m_engineMock, addField(m_section.get(), "FORWARD_BACKWARD", LooksBlocks::FORWARD_BACKWARD));
133137

134138
// Field values
135139
EXPECT_CALL(m_engineMock, addFieldValue(m_section.get(), "number", LooksBlocks::Number));
@@ -141,6 +145,10 @@ TEST_F(LooksBlocksTest, RegisterBlocks)
141145
EXPECT_CALL(m_engineMock, addFieldValue(m_section.get(), "MOSAIC", LooksBlocks::MosaicEffect));
142146
EXPECT_CALL(m_engineMock, addFieldValue(m_section.get(), "BRIGHTNESS", LooksBlocks::BrightnessEffect));
143147
EXPECT_CALL(m_engineMock, addFieldValue(m_section.get(), "GHOST", LooksBlocks::GhostEffect));
148+
EXPECT_CALL(m_engineMock, addFieldValue(m_section.get(), "front", LooksBlocks::Front));
149+
EXPECT_CALL(m_engineMock, addFieldValue(m_section.get(), "back", LooksBlocks::Back));
150+
EXPECT_CALL(m_engineMock, addFieldValue(m_section.get(), "forward", LooksBlocks::Forward));
151+
EXPECT_CALL(m_engineMock, addFieldValue(m_section.get(), "backward", LooksBlocks::Backward));
144152

145153
m_section->registerBlocks(&m_engineMock);
146154
}
@@ -2577,6 +2585,116 @@ TEST_F(LooksBlocksTest, RandomBackdropAndWait)
25772585
LooksBlocks::rng = RandomGenerator::instance().get();
25782586
}
25792587

2588+
TEST_F(LooksBlocksTest, GoToFrontBack)
2589+
{
2590+
Compiler compiler(&m_engineMock);
2591+
2592+
// go to [front] layer
2593+
auto block1 = std::make_shared<Block>("a", "looks_gotofrontback");
2594+
addDropdownField(block1, "FRONT_BACK", LooksBlocks::FRONT_BACK, "front", LooksBlocks::Front);
2595+
2596+
// go to [back] layer
2597+
auto block2 = std::make_shared<Block>("b", "looks_gotofrontback");
2598+
addDropdownField(block2, "FRONT_BACK", LooksBlocks::FRONT_BACK, "back", LooksBlocks::Back);
2599+
2600+
compiler.init();
2601+
2602+
EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::goToFront)).WillOnce(Return(0));
2603+
compiler.setBlock(block1);
2604+
LooksBlocks::compileGoToFrontBack(&compiler);
2605+
2606+
EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::goToBack)).WillOnce(Return(1));
2607+
compiler.setBlock(block2);
2608+
LooksBlocks::compileGoToFrontBack(&compiler);
2609+
2610+
compiler.end();
2611+
2612+
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_EXEC, 0, vm::OP_EXEC, 1, vm::OP_HALT }));
2613+
ASSERT_TRUE(compiler.constValues().empty());
2614+
}
2615+
2616+
TEST_F(LooksBlocksTest, GoToFrontBackImpl)
2617+
{
2618+
static unsigned int bytecode1[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT };
2619+
static unsigned int bytecode2[] = { vm::OP_START, vm::OP_EXEC, 1, vm::OP_HALT };
2620+
static BlockFunc functions[] = { &LooksBlocks::goToFront, &LooksBlocks::goToBack };
2621+
2622+
Sprite sprite;
2623+
2624+
VirtualMachine vm(&sprite, &m_engineMock, nullptr);
2625+
vm.setFunctions(functions);
2626+
2627+
EXPECT_CALL(m_engineMock, moveSpriteToFront(&sprite));
2628+
vm.setBytecode(bytecode1);
2629+
vm.run();
2630+
2631+
ASSERT_EQ(vm.registerCount(), 0);
2632+
2633+
EXPECT_CALL(m_engineMock, moveSpriteToBack(&sprite));
2634+
vm.reset();
2635+
vm.setBytecode(bytecode2);
2636+
vm.run();
2637+
2638+
ASSERT_EQ(vm.registerCount(), 0);
2639+
}
2640+
2641+
TEST_F(LooksBlocksTest, GoForwardBackwardLayers)
2642+
{
2643+
Compiler compiler(&m_engineMock);
2644+
2645+
// go [forward] (5) layers
2646+
auto block1 = std::make_shared<Block>("a", "looks_goforwardbackwardlayers");
2647+
addDropdownField(block1, "FORWARD_BACKWARD", LooksBlocks::FORWARD_BACKWARD, "forward", LooksBlocks::Forward);
2648+
addValueInput(block1, "NUM", LooksBlocks::NUM, 5);
2649+
2650+
// go [backward] (3) layers
2651+
auto block2 = std::make_shared<Block>("b", "looks_goforwardbackwardlayers");
2652+
addDropdownField(block2, "FORWARD_BACKWARD", LooksBlocks::FORWARD_BACKWARD, "backward", LooksBlocks::Backward);
2653+
addValueInput(block2, "NUM", LooksBlocks::NUM, 3);
2654+
2655+
compiler.init();
2656+
2657+
EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::goForwardLayers)).WillOnce(Return(0));
2658+
compiler.setBlock(block1);
2659+
LooksBlocks::compileGoForwardBackwardLayers(&compiler);
2660+
2661+
EXPECT_CALL(m_engineMock, functionIndex(&LooksBlocks::goBackwardLayers)).WillOnce(Return(1));
2662+
compiler.setBlock(block2);
2663+
LooksBlocks::compileGoForwardBackwardLayers(&compiler);
2664+
2665+
compiler.end();
2666+
2667+
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_CONST, 1, vm::OP_EXEC, 1, vm::OP_HALT }));
2668+
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 5, 3 }));
2669+
}
2670+
2671+
TEST_F(LooksBlocksTest, GoForwardBackwardLayersImpl)
2672+
{
2673+
static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_HALT };
2674+
static unsigned int bytecode2[] = { vm::OP_START, vm::OP_CONST, 1, vm::OP_EXEC, 1, vm::OP_HALT };
2675+
static BlockFunc functions[] = { &LooksBlocks::goForwardLayers, &LooksBlocks::goBackwardLayers };
2676+
static Value constValues[] = { 5, 3 };
2677+
2678+
Sprite sprite;
2679+
2680+
VirtualMachine vm(&sprite, &m_engineMock, nullptr);
2681+
vm.setFunctions(functions);
2682+
vm.setConstValues(constValues);
2683+
2684+
EXPECT_CALL(m_engineMock, moveSpriteForwardLayers(&sprite, 5));
2685+
vm.setBytecode(bytecode1);
2686+
vm.run();
2687+
2688+
ASSERT_EQ(vm.registerCount(), 0);
2689+
2690+
EXPECT_CALL(m_engineMock, moveSpriteBackwardLayers(&sprite, 3));
2691+
vm.reset();
2692+
vm.setBytecode(bytecode2);
2693+
vm.run();
2694+
2695+
ASSERT_EQ(vm.registerCount(), 0);
2696+
}
2697+
25802698
TEST_F(LooksBlocksTest, CostumeNumberName)
25812699
{
25822700
Compiler compiler(&m_engineMock);

test/engine/engine_test.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,36 @@ TEST(EngineTest, FpsProject)
116116
p.run();
117117
}
118118

119+
TEST(EngineTest, ExecutionOrder)
120+
{
121+
Project p("execution_order.sb3");
122+
ASSERT_TRUE(p.load());
123+
124+
p.run();
125+
126+
auto engine = p.engine();
127+
128+
Stage *stage = engine->stage();
129+
ASSERT_TRUE(stage);
130+
131+
ASSERT_LIST(stage, "order");
132+
auto list = GET_LIST(stage, "order");
133+
ASSERT_EQ(list->size(), 13);
134+
135+
ASSERT_EQ((*list)[0].toString(), "Sprite2");
136+
ASSERT_EQ((*list)[1].toString(), "Sprite3");
137+
ASSERT_EQ((*list)[2].toString(), "Sprite1");
138+
ASSERT_EQ((*list)[3].toString(), "Stage");
139+
ASSERT_EQ((*list)[4].toString(), "Sprite1 1");
140+
ASSERT_EQ((*list)[5].toString(), "Sprite1 2");
141+
ASSERT_EQ((*list)[6].toString(), "Sprite1 3");
142+
ASSERT_EQ((*list)[7].toString(), "Sprite2 msg");
143+
ASSERT_EQ((*list)[8].toString(), "Sprite3 msg");
144+
ASSERT_EQ((*list)[9].toString(), "Sprite1 1 msg");
145+
ASSERT_EQ((*list)[10].toString(), "Sprite1 2 msg");
146+
ASSERT_EQ((*list)[11].toString(), "Sprite1 3 msg");
147+
}
148+
119149
TEST(EngineTest, KeyState)
120150
{
121151
Engine engine;

test/execution_order.sb3

1.88 KB
Binary file not shown.

0 commit comments

Comments
 (0)