Skip to content

Commit 0e631b1

Browse files
committed
Implement looks_switchcostumeto block
1 parent 4fdef81 commit 0e631b1

File tree

3 files changed

+359
-0
lines changed

3 files changed

+359
-0
lines changed

src/blocks/looksblocks.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <scratchcpp/sprite.h>
1010
#include <scratchcpp/stringptr.h>
1111
#include <scratchcpp/value.h>
12+
#include <scratchcpp/input.h>
1213
#include <scratchcpp/field.h>
1314
#include <scratchcpp/igraphicseffect.h>
1415
#include <scratchcpp/scratchconfiguration.h>
@@ -47,6 +48,7 @@ void LooksBlocks::registerBlocks(IEngine *engine)
4748
engine->addCompileFunction(this, "looks_changesizeby", &compileChangeSizeBy);
4849
engine->addCompileFunction(this, "looks_setsizeto", &compileSetSizeTo);
4950
engine->addCompileFunction(this, "looks_size", &compileSize);
51+
engine->addCompileFunction(this, "looks_switchcostumeto", &compileSwitchCostumeTo);
5052
}
5153

5254
void LooksBlocks::onInit(IEngine *engine)
@@ -202,6 +204,13 @@ CompilerValue *LooksBlocks::compileSize(Compiler *compiler)
202204
return compiler->addTargetFunctionCall("looks_size", Compiler::StaticType::Number);
203205
}
204206

207+
CompilerValue *LooksBlocks::compileSwitchCostumeTo(Compiler *compiler)
208+
{
209+
auto costume = compiler->addInput("COSTUME");
210+
compiler->addTargetFunctionCall("looks_switchcostumeto", Compiler::StaticType::Void, { Compiler::StaticType::Unknown }, { costume });
211+
return nullptr;
212+
}
213+
205214
extern "C" void looks_start_stack_timer(ExecutionContext *ctx, double duration)
206215
{
207216
ctx->stackTimer()->start(duration);
@@ -285,3 +294,59 @@ extern "C" double looks_size(Sprite *sprite)
285294
{
286295
return sprite->size();
287296
}
297+
298+
extern "C" void looks_set_costume_by_index(Target *target, long index)
299+
{
300+
const size_t costumeCount = target->costumes().size();
301+
302+
if (index < 0)
303+
index = (costumeCount + index % (-costumeCount)) % costumeCount;
304+
else if (index >= costumeCount)
305+
index = index % costumeCount;
306+
307+
target->setCostumeIndex(index);
308+
}
309+
310+
extern "C" void looks_nextcostume(Target *target)
311+
{
312+
looks_set_costume_by_index(target, target->costumeIndex() + 1);
313+
}
314+
315+
extern "C" void looks_previouscostume(Target *target)
316+
{
317+
looks_set_costume_by_index(target, target->costumeIndex() - 1);
318+
}
319+
320+
extern "C" void looks_switchcostumeto(Target *target, const ValueData *costume)
321+
{
322+
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L389-L413
323+
if (!value_isString(costume)) {
324+
// Numbers should be treated as costume indices, always
325+
if (value_isNaN(costume) || value_isInfinity(costume) || value_isNegativeInfinity(costume))
326+
target->setCostumeIndex(0);
327+
else
328+
looks_set_costume_by_index(target, value_toLong(costume) - 1);
329+
} else {
330+
// Strings should be treated as costume names, where possible
331+
// TODO: Use UTF-16 in Target
332+
// StringPtr *nameStr = value_toStringPtr(costume);
333+
std::string nameStr;
334+
value_toString(costume, &nameStr);
335+
const int costumeIndex = target->findCostume(nameStr);
336+
337+
auto it = std::find_if(nameStr.begin(), nameStr.end(), [](char c) { return !std::isspace(c); });
338+
bool isWhiteSpace = (it == nameStr.end());
339+
340+
if (costumeIndex != -1)
341+
looks_set_costume_by_index(target, costumeIndex);
342+
else if (nameStr == "next costume")
343+
looks_nextcostume(target);
344+
else if (nameStr == "previous costume") {
345+
looks_previouscostume(target);
346+
// Try to cast the string to a number (and treat it as a costume index)
347+
// Pure whitespace should not be treated as a number
348+
// Note: isNaN will cast the string to a number before checking if it's NaN
349+
} else if (value_isValidNumber(costume) && !isWhiteSpace)
350+
looks_set_costume_by_index(target, value_toLong(costume) - 1);
351+
}
352+
}

src/blocks/looksblocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class LooksBlocks : public IExtension
3939
static CompilerValue *compileChangeSizeBy(Compiler *compiler);
4040
static CompilerValue *compileSetSizeTo(Compiler *compiler);
4141
static CompilerValue *compileSize(Compiler *compiler);
42+
static CompilerValue *compileSwitchCostumeTo(Compiler *compiler);
4243
};
4344

4445
} // namespace libscratchcpp

0 commit comments

Comments
 (0)