Skip to content

Commit 81d15b6

Browse files
committed
Implement looks_switchcostumeto block
1 parent 2d19185 commit 81d15b6

File tree

3 files changed

+515
-1
lines changed

3 files changed

+515
-1
lines changed

src/blocks/looksblocks.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <scratchcpp/iengine.h>
44
#include <scratchcpp/compiler.h>
55
#include <scratchcpp/sprite.h>
6+
#include <scratchcpp/input.h>
67
#include <scratchcpp/field.h>
78
#include <scratchcpp/costume.h>
89

@@ -23,11 +24,13 @@ void LooksBlocks::registerBlocks(IEngine *engine)
2324
engine->addCompileFunction(this, "looks_changesizeby", &compileChangeSizeBy);
2425
engine->addCompileFunction(this, "looks_setsizeto", &compileSetSizeTo);
2526
engine->addCompileFunction(this, "looks_size", &compileSize);
27+
engine->addCompileFunction(this, "looks_switchcostumeto", &compileSwitchCostumeTo);
2628
engine->addCompileFunction(this, "looks_costumenumbername", &compileCostumeNumberName);
2729

2830
// Inputs
2931
engine->addInput(this, "CHANGE", CHANGE);
3032
engine->addInput(this, "SIZE", SIZE);
33+
engine->addInput(this, "COSTUME", COSTUME);
3134

3235
// Fields
3336
engine->addField(this, "NUMBER_NAME", NUMBER_NAME);
@@ -64,6 +67,43 @@ void LooksBlocks::compileSize(Compiler *compiler)
6467
compiler->addFunctionCall(&size);
6568
}
6669

70+
void LooksBlocks::compileSwitchCostumeTo(Compiler *compiler)
71+
{
72+
Target *target = compiler->target();
73+
74+
if (!target)
75+
return;
76+
77+
Input *input = compiler->input(COSTUME);
78+
79+
if (input->type() != Input::Type::ObscuredShadow) {
80+
assert(input->pointsToDropdownMenu());
81+
std::string value = input->selectedMenuItem();
82+
int index = target->findCostume(value);
83+
84+
if (index == -1) {
85+
if (value == "next costume")
86+
compiler->addFunctionCall(&nextCostume);
87+
else if (value == "previous costume")
88+
compiler->addFunctionCall(&previousCostume);
89+
else {
90+
Value v(value);
91+
92+
if (v.type() == Value::Type::Integer) {
93+
compiler->addConstValue(v.toLong() - 1);
94+
compiler->addFunctionCall(&switchCostumeToByIndex);
95+
}
96+
}
97+
} else {
98+
compiler->addConstValue(index);
99+
compiler->addFunctionCall(&switchCostumeToByIndex);
100+
}
101+
} else {
102+
compiler->addInput(input);
103+
compiler->addFunctionCall(&switchCostumeTo);
104+
}
105+
}
106+
67107
void LooksBlocks::compileCostumeNumberName(Compiler *compiler)
68108
{
69109
int option = compiler->field(NUMBER_NAME)->specialValueId();
@@ -131,6 +171,70 @@ unsigned int LooksBlocks::size(VirtualMachine *vm)
131171
return 0;
132172
}
133173

174+
void LooksBlocks::setCostumeByIndex(Target *target, long index)
175+
{
176+
// TODO: Remove this (#248)
177+
std::size_t costumeCount = target->costumes().size();
178+
if (index < 0 || index >= costumeCount) {
179+
if (index < 0)
180+
index = std::fmod(costumeCount + std::fmod(index, -costumeCount), costumeCount);
181+
else
182+
index = std::fmod(index, costumeCount);
183+
}
184+
185+
target->setCurrentCostume(index + 1);
186+
}
187+
188+
unsigned int LooksBlocks::switchCostumeToByIndex(VirtualMachine *vm)
189+
{
190+
if (Target *target = vm->target())
191+
setCostumeByIndex(target, vm->getInput(0, 1)->toLong());
192+
193+
return 1;
194+
}
195+
196+
unsigned int LooksBlocks::switchCostumeTo(VirtualMachine *vm)
197+
{
198+
Target *target = vm->target();
199+
200+
if (!target)
201+
return 1;
202+
203+
const Value *name = vm->getInput(0, 1);
204+
std::string nameStr = name->toString();
205+
int index = target->findCostume(nameStr);
206+
207+
if (index == -1) {
208+
if (nameStr == "next costume")
209+
nextCostume(vm);
210+
else if (nameStr == "previous costume")
211+
previousCostume(vm);
212+
else {
213+
if (name->type() == Value::Type::Integer)
214+
setCostumeByIndex(target, name->toLong() - 1);
215+
}
216+
} else
217+
setCostumeByIndex(target, index);
218+
219+
return 1;
220+
}
221+
222+
unsigned int LooksBlocks::nextCostume(VirtualMachine *vm)
223+
{
224+
if (Target *target = vm->target())
225+
setCostumeByIndex(target, target->currentCostume());
226+
227+
return 0;
228+
}
229+
230+
unsigned int LooksBlocks::previousCostume(VirtualMachine *vm)
231+
{
232+
if (Target *target = vm->target())
233+
setCostumeByIndex(target, target->currentCostume() - 2);
234+
235+
return 0;
236+
}
237+
134238
unsigned int LooksBlocks::costumeNumber(VirtualMachine *vm)
135239
{
136240
if (Target *target = vm->target())

src/blocks/looksblocks.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@
77
namespace libscratchcpp
88
{
99

10+
class Target;
11+
1012
/*! \brief The LooksBlocks class contains the implementation of looks blocks. */
1113
class LooksBlocks : public IBlockSection
1214
{
1315
public:
1416
enum Inputs
1517
{
1618
CHANGE,
17-
SIZE
19+
SIZE,
20+
COSTUME
1821
};
1922

2023
enum Fields
@@ -37,13 +40,21 @@ class LooksBlocks : public IBlockSection
3740
static void compileChangeSizeBy(Compiler *compiler);
3841
static void compileSetSizeTo(Compiler *compiler);
3942
static void compileSize(Compiler *compiler);
43+
static void compileSwitchCostumeTo(Compiler *compiler);
4044
static void compileCostumeNumberName(Compiler *compiler);
4145

4246
static unsigned int show(VirtualMachine *vm);
4347
static unsigned int hide(VirtualMachine *vm);
4448
static unsigned int changeSizeBy(VirtualMachine *vm);
4549
static unsigned int setSizeTo(VirtualMachine *vm);
4650
static unsigned int size(VirtualMachine *vm);
51+
52+
static void setCostumeByIndex(Target *target, long index);
53+
static unsigned int switchCostumeToByIndex(VirtualMachine *vm);
54+
static unsigned int switchCostumeTo(VirtualMachine *vm);
55+
static unsigned int nextCostume(VirtualMachine *vm);
56+
static unsigned int previousCostume(VirtualMachine *vm);
57+
4758
static unsigned int costumeNumber(VirtualMachine *vm);
4859
static unsigned int costumeName(VirtualMachine *vm);
4960
};

0 commit comments

Comments
 (0)