Skip to content

Commit 94ccf7e

Browse files
authored
Merge pull request #244 from scratchcpp/looks_blocks2
Implement looks blocks (part 2)
2 parents 331fd98 + 30e37e9 commit 94ccf7e

File tree

3 files changed

+1480
-1
lines changed

3 files changed

+1480
-1
lines changed

src/blocks/looksblocks.cpp

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33
#include <scratchcpp/iengine.h>
44
#include <scratchcpp/compiler.h>
55
#include <scratchcpp/sprite.h>
6+
#include <scratchcpp/stage.h>
7+
#include <scratchcpp/input.h>
8+
#include <scratchcpp/field.h>
9+
#include <scratchcpp/costume.h>
610

711
#include "looksblocks.h"
12+
#include "../engine/internal/randomgenerator.h"
813

914
using namespace libscratchcpp;
1015

16+
IRandomGenerator *LooksBlocks::rng = nullptr;
17+
1118
std::string LooksBlocks::name() const
1219
{
1320
return "Looks";
@@ -21,10 +28,25 @@ void LooksBlocks::registerBlocks(IEngine *engine)
2128
engine->addCompileFunction(this, "looks_changesizeby", &compileChangeSizeBy);
2229
engine->addCompileFunction(this, "looks_setsizeto", &compileSetSizeTo);
2330
engine->addCompileFunction(this, "looks_size", &compileSize);
31+
engine->addCompileFunction(this, "looks_switchcostumeto", &compileSwitchCostumeTo);
32+
engine->addCompileFunction(this, "looks_nextcostume", &compileNextCostume);
33+
engine->addCompileFunction(this, "looks_switchbackdropto", &compileSwitchBackdropTo);
34+
engine->addCompileFunction(this, "looks_nextbackdrop", &compileNextBackdrop);
35+
engine->addCompileFunction(this, "looks_costumenumbername", &compileCostumeNumberName);
36+
engine->addCompileFunction(this, "looks_backdropnumbername", &compileBackdropNumberName);
2437

2538
// Inputs
2639
engine->addInput(this, "CHANGE", CHANGE);
2740
engine->addInput(this, "SIZE", SIZE);
41+
engine->addInput(this, "COSTUME", COSTUME);
42+
engine->addInput(this, "BACKDROP", BACKDROP);
43+
44+
// Fields
45+
engine->addField(this, "NUMBER_NAME", NUMBER_NAME);
46+
47+
// Field values
48+
engine->addFieldValue(this, "number", Number);
49+
engine->addFieldValue(this, "name", Name);
2850
}
2951

3052
void LooksBlocks::compileShow(Compiler *compiler)
@@ -54,6 +76,122 @@ void LooksBlocks::compileSize(Compiler *compiler)
5476
compiler->addFunctionCall(&size);
5577
}
5678

79+
void LooksBlocks::compileSwitchCostumeTo(Compiler *compiler)
80+
{
81+
Target *target = compiler->target();
82+
83+
if (!target)
84+
return;
85+
86+
Input *input = compiler->input(COSTUME);
87+
88+
if (input->type() != Input::Type::ObscuredShadow) {
89+
assert(input->pointsToDropdownMenu());
90+
std::string value = input->selectedMenuItem();
91+
int index = target->findCostume(value);
92+
93+
if (index == -1) {
94+
if (value == "next costume")
95+
compiler->addFunctionCall(&nextCostume);
96+
else if (value == "previous costume")
97+
compiler->addFunctionCall(&previousCostume);
98+
else {
99+
Value v(value);
100+
101+
if (v.type() == Value::Type::Integer) {
102+
compiler->addConstValue(v.toLong() - 1);
103+
compiler->addFunctionCall(&switchCostumeToByIndex);
104+
}
105+
}
106+
} else {
107+
compiler->addConstValue(index);
108+
compiler->addFunctionCall(&switchCostumeToByIndex);
109+
}
110+
} else {
111+
compiler->addInput(input);
112+
compiler->addFunctionCall(&switchCostumeTo);
113+
}
114+
}
115+
116+
void LooksBlocks::compileNextCostume(Compiler *compiler)
117+
{
118+
compiler->addFunctionCall(&nextCostume);
119+
}
120+
121+
void LooksBlocks::compileSwitchBackdropTo(Compiler *compiler)
122+
{
123+
Stage *stage = compiler->engine()->stage();
124+
125+
if (!stage)
126+
return;
127+
128+
Input *input = compiler->input(BACKDROP);
129+
130+
if (input->type() != Input::Type::ObscuredShadow) {
131+
assert(input->pointsToDropdownMenu());
132+
std::string value = input->selectedMenuItem();
133+
int index = stage->findCostume(value);
134+
135+
if (index == -1) {
136+
if (value == "next backdrop")
137+
compiler->addFunctionCall(&nextBackdrop);
138+
else if (value == "previous backdrop")
139+
compiler->addFunctionCall(&previousBackdrop);
140+
else if (value == "random backdrop")
141+
compiler->addFunctionCall(&randomBackdrop);
142+
else {
143+
Value v(value);
144+
145+
if (v.type() == Value::Type::Integer) {
146+
compiler->addConstValue(v.toLong() - 1);
147+
compiler->addFunctionCall(&switchBackdropToByIndex);
148+
}
149+
}
150+
} else {
151+
compiler->addConstValue(index);
152+
compiler->addFunctionCall(&switchBackdropToByIndex);
153+
}
154+
} else {
155+
compiler->addInput(input);
156+
compiler->addFunctionCall(&switchBackdropTo);
157+
}
158+
}
159+
160+
void LooksBlocks::compileNextBackdrop(Compiler *compiler)
161+
{
162+
compiler->addFunctionCall(&nextBackdrop);
163+
}
164+
165+
void LooksBlocks::compileCostumeNumberName(Compiler *compiler)
166+
{
167+
int option = compiler->field(NUMBER_NAME)->specialValueId();
168+
169+
switch (option) {
170+
case Number:
171+
compiler->addFunctionCall(&costumeNumber);
172+
break;
173+
174+
case Name:
175+
compiler->addFunctionCall(&costumeName);
176+
break;
177+
}
178+
}
179+
180+
void LooksBlocks::compileBackdropNumberName(Compiler *compiler)
181+
{
182+
int option = compiler->field(NUMBER_NAME)->specialValueId();
183+
184+
switch (option) {
185+
case Number:
186+
compiler->addFunctionCall(&backdropNumber);
187+
break;
188+
189+
case Name:
190+
compiler->addFunctionCall(&backdropName);
191+
break;
192+
}
193+
}
194+
57195
unsigned int LooksBlocks::show(VirtualMachine *vm)
58196
{
59197
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());
@@ -105,3 +243,184 @@ unsigned int LooksBlocks::size(VirtualMachine *vm)
105243

106244
return 0;
107245
}
246+
247+
void LooksBlocks::setCostumeByIndex(Target *target, long index)
248+
{
249+
// TODO: Remove this (#248)
250+
std::size_t costumeCount = target->costumes().size();
251+
if (index < 0 || index >= costumeCount) {
252+
if (index < 0)
253+
index = std::fmod(costumeCount + std::fmod(index, -costumeCount), costumeCount);
254+
else
255+
index = std::fmod(index, costumeCount);
256+
}
257+
258+
target->setCurrentCostume(index + 1);
259+
}
260+
261+
unsigned int LooksBlocks::switchCostumeToByIndex(VirtualMachine *vm)
262+
{
263+
if (Target *target = vm->target())
264+
setCostumeByIndex(target, vm->getInput(0, 1)->toLong());
265+
266+
return 1;
267+
}
268+
269+
unsigned int LooksBlocks::switchCostumeTo(VirtualMachine *vm)
270+
{
271+
Target *target = vm->target();
272+
273+
if (!target)
274+
return 1;
275+
276+
const Value *name = vm->getInput(0, 1);
277+
std::string nameStr = name->toString();
278+
int index = target->findCostume(nameStr);
279+
280+
if (index == -1) {
281+
if (nameStr == "next costume")
282+
nextCostume(vm);
283+
else if (nameStr == "previous costume")
284+
previousCostume(vm);
285+
else {
286+
if (name->type() == Value::Type::Integer)
287+
setCostumeByIndex(target, name->toLong() - 1);
288+
}
289+
} else
290+
setCostumeByIndex(target, index);
291+
292+
return 1;
293+
}
294+
295+
unsigned int LooksBlocks::nextCostume(VirtualMachine *vm)
296+
{
297+
if (Target *target = vm->target())
298+
setCostumeByIndex(target, target->currentCostume());
299+
300+
return 0;
301+
}
302+
303+
unsigned int LooksBlocks::previousCostume(VirtualMachine *vm)
304+
{
305+
if (Target *target = vm->target())
306+
setCostumeByIndex(target, target->currentCostume() - 2);
307+
308+
return 0;
309+
}
310+
311+
unsigned int LooksBlocks::switchBackdropToByIndex(VirtualMachine *vm)
312+
{
313+
if (Stage *stage = vm->engine()->stage())
314+
setCostumeByIndex(stage, vm->getInput(0, 1)->toLong());
315+
316+
return 1;
317+
}
318+
319+
unsigned int LooksBlocks::switchBackdropTo(VirtualMachine *vm)
320+
{
321+
Stage *stage = vm->engine()->stage();
322+
323+
if (!stage)
324+
return 1;
325+
326+
const Value *name = vm->getInput(0, 1);
327+
std::string nameStr = name->toString();
328+
int index = stage->findCostume(nameStr);
329+
330+
if (index == -1) {
331+
if (nameStr == "next backdrop")
332+
nextBackdrop(vm);
333+
else if (nameStr == "previous backdrop")
334+
previousBackdrop(vm);
335+
else if (nameStr == "random backdrop") {
336+
randomBackdrop(vm);
337+
} else {
338+
if (name->type() == Value::Type::Integer)
339+
setCostumeByIndex(stage, name->toLong() - 1);
340+
}
341+
} else
342+
setCostumeByIndex(stage, index);
343+
344+
return 1;
345+
}
346+
347+
unsigned int LooksBlocks::nextBackdrop(VirtualMachine *vm)
348+
{
349+
if (Stage *stage = vm->engine()->stage())
350+
setCostumeByIndex(stage, stage->currentCostume());
351+
352+
return 0;
353+
}
354+
355+
unsigned int LooksBlocks::previousBackdrop(VirtualMachine *vm)
356+
{
357+
if (Stage *stage = vm->engine()->stage())
358+
setCostumeByIndex(stage, stage->currentCostume() - 2);
359+
360+
return 0;
361+
}
362+
363+
unsigned int LooksBlocks::randomBackdrop(VirtualMachine *vm)
364+
{
365+
if (!rng)
366+
rng = RandomGenerator::instance().get();
367+
368+
if (Stage *stage = vm->engine()->stage()) {
369+
std::size_t count = stage->costumes().size();
370+
371+
if (count > 0)
372+
stage->setCurrentCostume(rng->randint(1, count));
373+
}
374+
375+
return 0;
376+
}
377+
378+
unsigned int LooksBlocks::costumeNumber(VirtualMachine *vm)
379+
{
380+
if (Target *target = vm->target())
381+
vm->addReturnValue(target->currentCostume());
382+
else
383+
vm->addReturnValue(0);
384+
385+
return 0;
386+
}
387+
388+
unsigned int LooksBlocks::costumeName(VirtualMachine *vm)
389+
{
390+
if (Target *target = vm->target()) {
391+
auto costume = target->costumeAt(target->currentCostume() - 1);
392+
393+
if (costume)
394+
vm->addReturnValue(costume->name());
395+
else
396+
vm->addReturnValue("");
397+
} else
398+
vm->addReturnValue("");
399+
400+
return 0;
401+
}
402+
403+
unsigned int LooksBlocks::backdropNumber(VirtualMachine *vm)
404+
{
405+
if (Stage *stage = vm->engine()->stage())
406+
vm->addReturnValue(stage->currentCostume());
407+
else
408+
vm->addReturnValue(0);
409+
410+
return 0;
411+
}
412+
413+
unsigned int LooksBlocks::backdropName(VirtualMachine *vm)
414+
{
415+
if (Stage *stage = vm->engine()->stage()) {
416+
auto costume = stage->costumeAt(stage->currentCostume() - 1);
417+
418+
if (costume)
419+
vm->addReturnValue(costume->name());
420+
else
421+
vm->addReturnValue("");
422+
} else
423+
vm->addReturnValue("");
424+
425+
return 0;
426+
}

0 commit comments

Comments
 (0)