33#include < scratchcpp/iengine.h>
44#include < scratchcpp/compiler.h>
55#include < scratchcpp/sprite.h>
6+ #include < scratchcpp/stage.h>
67#include < scratchcpp/input.h>
78#include < scratchcpp/field.h>
89#include < scratchcpp/costume.h>
910
1011#include " looksblocks.h"
12+ #include " ../engine/internal/randomgenerator.h"
1113
1214using namespace libscratchcpp ;
1315
16+ IRandomGenerator *LooksBlocks::rng = nullptr ;
17+
1418std::string LooksBlocks::name () const
1519{
1620 return " Looks" ;
@@ -26,12 +30,14 @@ void LooksBlocks::registerBlocks(IEngine *engine)
2630 engine->addCompileFunction (this , " looks_size" , &compileSize);
2731 engine->addCompileFunction (this , " looks_switchcostumeto" , &compileSwitchCostumeTo);
2832 engine->addCompileFunction (this , " looks_nextcostume" , &compileNextCostume);
33+ engine->addCompileFunction (this , " looks_switchbackdropto" , &compileSwitchBackdropTo);
2934 engine->addCompileFunction (this , " looks_costumenumbername" , &compileCostumeNumberName);
3035
3136 // Inputs
3237 engine->addInput (this , " CHANGE" , CHANGE);
3338 engine->addInput (this , " SIZE" , SIZE);
3439 engine->addInput (this , " COSTUME" , COSTUME);
40+ engine->addInput (this , " BACKDROP" , BACKDROP);
3541
3642 // Fields
3743 engine->addField (this , " NUMBER_NAME" , NUMBER_NAME);
@@ -110,6 +116,45 @@ void LooksBlocks::compileNextCostume(Compiler *compiler)
110116 compiler->addFunctionCall (&nextCostume);
111117}
112118
119+ void LooksBlocks::compileSwitchBackdropTo (Compiler *compiler)
120+ {
121+ Stage *stage = compiler->engine ()->stage ();
122+
123+ if (!stage)
124+ return ;
125+
126+ Input *input = compiler->input (BACKDROP);
127+
128+ if (input->type () != Input::Type::ObscuredShadow) {
129+ assert (input->pointsToDropdownMenu ());
130+ std::string value = input->selectedMenuItem ();
131+ int index = stage->findCostume (value);
132+
133+ if (index == -1 ) {
134+ if (value == " next backdrop" )
135+ compiler->addFunctionCall (&nextBackdrop);
136+ else if (value == " previous backdrop" )
137+ compiler->addFunctionCall (&previousBackdrop);
138+ else if (value == " random backdrop" )
139+ compiler->addFunctionCall (&randomBackdrop);
140+ else {
141+ Value v (value);
142+
143+ if (v.type () == Value::Type::Integer) {
144+ compiler->addConstValue (v.toLong () - 1 );
145+ compiler->addFunctionCall (&switchBackdropToByIndex);
146+ }
147+ }
148+ } else {
149+ compiler->addConstValue (index);
150+ compiler->addFunctionCall (&switchBackdropToByIndex);
151+ }
152+ } else {
153+ compiler->addInput (input);
154+ compiler->addFunctionCall (&switchBackdropTo);
155+ }
156+ }
157+
113158void LooksBlocks::compileCostumeNumberName (Compiler *compiler)
114159{
115160 int option = compiler->field (NUMBER_NAME)->specialValueId ();
@@ -241,6 +286,73 @@ unsigned int LooksBlocks::previousCostume(VirtualMachine *vm)
241286 return 0 ;
242287}
243288
289+ unsigned int LooksBlocks::switchBackdropToByIndex (VirtualMachine *vm)
290+ {
291+ if (Stage *stage = vm->engine ()->stage ())
292+ setCostumeByIndex (stage, vm->getInput (0 , 1 )->toLong ());
293+
294+ return 1 ;
295+ }
296+
297+ unsigned int LooksBlocks::switchBackdropTo (VirtualMachine *vm)
298+ {
299+ Stage *stage = vm->engine ()->stage ();
300+
301+ if (!stage)
302+ return 1 ;
303+
304+ const Value *name = vm->getInput (0 , 1 );
305+ std::string nameStr = name->toString ();
306+ int index = stage->findCostume (nameStr);
307+
308+ if (index == -1 ) {
309+ if (nameStr == " next backdrop" )
310+ nextBackdrop (vm);
311+ else if (nameStr == " previous backdrop" )
312+ previousBackdrop (vm);
313+ else if (nameStr == " random backdrop" ) {
314+ randomBackdrop (vm);
315+ } else {
316+ if (name->type () == Value::Type::Integer)
317+ setCostumeByIndex (stage, name->toLong () - 1 );
318+ }
319+ } else
320+ setCostumeByIndex (stage, index);
321+
322+ return 1 ;
323+ }
324+
325+ unsigned int LooksBlocks::nextBackdrop (VirtualMachine *vm)
326+ {
327+ if (Stage *stage = vm->engine ()->stage ())
328+ setCostumeByIndex (stage, stage->currentCostume ());
329+
330+ return 0 ;
331+ }
332+
333+ unsigned int LooksBlocks::previousBackdrop (VirtualMachine *vm)
334+ {
335+ if (Stage *stage = vm->engine ()->stage ())
336+ setCostumeByIndex (stage, stage->currentCostume () - 2 );
337+
338+ return 0 ;
339+ }
340+
341+ unsigned int LooksBlocks::randomBackdrop (VirtualMachine *vm)
342+ {
343+ if (!rng)
344+ rng = RandomGenerator::instance ().get ();
345+
346+ if (Stage *stage = vm->engine ()->stage ()) {
347+ std::size_t count = stage->costumes ().size ();
348+
349+ if (count > 0 )
350+ stage->setCurrentCostume (rng->randint (1 , count));
351+ }
352+
353+ return 0 ;
354+ }
355+
244356unsigned int LooksBlocks::costumeNumber (VirtualMachine *vm)
245357{
246358 if (Target *target = vm->target ())
0 commit comments