Skip to content

Commit 289dd14

Browse files
committed
Implement looks_switchbackdropto block
1 parent 5438baf commit 289dd14

File tree

3 files changed

+681
-0
lines changed

3 files changed

+681
-0
lines changed

src/blocks/looksblocks.cpp

+69
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
#include <scratchcpp/compilerconstant.h>
66
#include <scratchcpp/executioncontext.h>
77
#include <scratchcpp/istacktimer.h>
8+
#include <scratchcpp/irandomgenerator.h>
89
#include <scratchcpp/thread.h>
910
#include <scratchcpp/sprite.h>
11+
#include <scratchcpp/stage.h>
12+
#include <scratchcpp/costume.h>
1013
#include <scratchcpp/stringptr.h>
1114
#include <scratchcpp/value.h>
1215
#include <scratchcpp/input.h>
@@ -50,6 +53,7 @@ void LooksBlocks::registerBlocks(IEngine *engine)
5053
engine->addCompileFunction(this, "looks_size", &compileSize);
5154
engine->addCompileFunction(this, "looks_switchcostumeto", &compileSwitchCostumeTo);
5255
engine->addCompileFunction(this, "looks_nextcostume", &compileNextCostume);
56+
engine->addCompileFunction(this, "looks_switchbackdropto", &compileSwitchBackdropTo);
5357
}
5458

5559
void LooksBlocks::onInit(IEngine *engine)
@@ -218,6 +222,16 @@ CompilerValue *LooksBlocks::compileNextCostume(Compiler *compiler)
218222
return nullptr;
219223
}
220224

225+
CompilerValue *LooksBlocks::compileSwitchBackdropTo(Compiler *compiler)
226+
{
227+
auto backdrop = compiler->addInput("BACKDROP");
228+
auto wait = compiler->addConstValue(false);
229+
compiler->addFunctionCallWithCtx("looks_switchbackdropto", Compiler::StaticType::Void, { Compiler::StaticType::Unknown }, { backdrop });
230+
compiler->addFunctionCallWithCtx("looks_start_backdrop_scripts", Compiler::StaticType::Void, { Compiler::StaticType::Bool }, { wait });
231+
232+
return nullptr;
233+
}
234+
221235
extern "C" void looks_start_stack_timer(ExecutionContext *ctx, double duration)
222236
{
223237
ctx->stackTimer()->start(duration);
@@ -324,6 +338,14 @@ extern "C" void looks_previouscostume(Target *target)
324338
looks_set_costume_by_index(target, target->costumeIndex() - 1);
325339
}
326340

341+
void looks_randomcostume(Target *target, IRandomGenerator *rng)
342+
{
343+
size_t count = target->costumes().size();
344+
345+
if (count > 1)
346+
looks_set_costume_by_index(target, rng->randintExcept(0, count - 1, target->costumeIndex())); // exclude current costume
347+
}
348+
327349
extern "C" void looks_switchcostumeto(Target *target, const ValueData *costume)
328350
{
329351
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L389-L413
@@ -356,3 +378,50 @@ extern "C" void looks_switchcostumeto(Target *target, const ValueData *costume)
356378
looks_set_costume_by_index(target, value_toLong(costume) - 1);
357379
}
358380
}
381+
382+
extern "C" void looks_start_backdrop_scripts(ExecutionContext *ctx, bool wait)
383+
{
384+
IEngine *engine = ctx->engine();
385+
Stage *stage = engine->stage();
386+
Costume *backdrop = stage->currentCostume().get();
387+
388+
if (backdrop)
389+
engine->startBackdropScripts(backdrop->broadcast(), ctx->thread(), wait);
390+
}
391+
392+
extern "C" void looks_switchbackdropto(ExecutionContext *ctx, const ValueData *backdrop)
393+
{
394+
Stage *stage = ctx->engine()->stage();
395+
396+
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L389-L413
397+
if (!value_isString(backdrop)) {
398+
// Numbers should be treated as costume indices, always
399+
if (value_isNaN(backdrop) || value_isInfinity(backdrop) || value_isNegativeInfinity(backdrop))
400+
stage->setCostumeIndex(0);
401+
else
402+
looks_set_costume_by_index(stage, value_toLong(backdrop) - 1);
403+
} else {
404+
// Strings should be treated as costume names, where possible
405+
// TODO: Use UTF-16 in Target
406+
// StringPtr *nameStr = value_toStringPtr(backdrop);
407+
std::string nameStr;
408+
value_toString(backdrop, &nameStr);
409+
const int costumeIndex = stage->findCostume(nameStr);
410+
411+
auto it = std::find_if(nameStr.begin(), nameStr.end(), [](char c) { return !std::isspace(c); });
412+
bool isWhiteSpace = (it == nameStr.end());
413+
414+
if (costumeIndex != -1)
415+
looks_set_costume_by_index(stage, costumeIndex);
416+
else if (nameStr == "next backdrop")
417+
looks_nextcostume(stage);
418+
else if (nameStr == "previous backdrop")
419+
looks_previouscostume(stage);
420+
else if (nameStr == "random backdrop") {
421+
looks_randomcostume(stage, ctx->rng());
422+
// Try to cast the string to a number (and treat it as a costume index)
423+
// Pure whitespace should not be treated as a number
424+
} else if (value_isValidNumber(backdrop) && !isWhiteSpace)
425+
looks_set_costume_by_index(stage, value_toLong(backdrop) - 1);
426+
}
427+
}

src/blocks/looksblocks.h

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class LooksBlocks : public IExtension
4141
static CompilerValue *compileSize(Compiler *compiler);
4242
static CompilerValue *compileSwitchCostumeTo(Compiler *compiler);
4343
static CompilerValue *compileNextCostume(Compiler *compiler);
44+
static CompilerValue *compileSwitchBackdropTo(Compiler *compiler);
4445
};
4546

4647
} // namespace libscratchcpp

0 commit comments

Comments
 (0)