Skip to content

Commit 9edda43

Browse files
committed
fix #522: Fix switch costume/backdrop block behavior
1 parent 9cc953c commit 9edda43

File tree

2 files changed

+292
-56
lines changed

2 files changed

+292
-56
lines changed

src/blocks/looksblocks.cpp

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -835,26 +835,41 @@ void LooksBlocks::setCostumeByIndex(Target *target, long index)
835835

836836
unsigned int LooksBlocks::switchCostumeTo(VirtualMachine *vm)
837837
{
838+
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L389-L413
838839
Target *target = vm->target();
839840

840841
if (!target)
841842
return 1;
842843

843844
const Value *name = vm->getInput(0, 1);
844-
std::string nameStr = name->toString();
845-
int index = target->findCostume(nameStr);
846845

847-
if (index == -1) {
848-
if (nameStr == "next costume")
846+
if (!name->isString()) {
847+
// Numbers should be treated as costume indices, always
848+
if (name->isNaN() || name->isInfinity() || name->isNegativeInfinity())
849+
target->setCostumeIndex(0);
850+
else
851+
setCostumeByIndex(target, name->toLong() - 1);
852+
} else {
853+
// Strings should be treated as costume names, where possible
854+
const int costumeIndex = target->findCostume(name->toString());
855+
std::string nameStr = name->toString();
856+
857+
auto it = std::find_if(nameStr.begin(), nameStr.end(), [](char c) { return !std::isspace(c); });
858+
bool isWhiteSpace = (it == nameStr.end());
859+
860+
if (costumeIndex != -1) {
861+
setCostumeByIndex(target, costumeIndex);
862+
} else if (nameStr == "next costume") {
849863
nextCostume(vm);
850-
else if (nameStr == "previous costume")
864+
} else if (nameStr == "previous costume") {
851865
previousCostume(vm);
852-
else {
853-
if (name->isValidNumber())
854-
setCostumeByIndex(target, name->toLong() - 1);
866+
// Try to cast the string to a number (and treat it as a costume index)
867+
// Pure whitespace should not be treated as a number
868+
// Note: isNaN will cast the string to a number before checking if it's NaN
869+
} else if (!(name->isNaN() || isWhiteSpace)) {
870+
target->setCostumeIndex(name->toInt() - 1);
855871
}
856-
} else
857-
setCostumeByIndex(target, index);
872+
}
858873

859874
return 1;
860875
}
@@ -885,28 +900,43 @@ void LooksBlocks::startBackdropScripts(VirtualMachine *vm, bool wait)
885900

886901
void LooksBlocks::switchBackdropToImpl(VirtualMachine *vm)
887902
{
903+
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L423-L462
888904
Stage *stage = vm->engine()->stage();
889905

890906
if (!stage)
891907
return;
892908

893909
const Value *name = vm->getInput(0, 1);
894-
std::string nameStr = name->toString();
895-
int index = stage->findCostume(nameStr);
896910

897-
if (index == -1) {
898-
if (nameStr == "next backdrop")
911+
if (!name->isString()) {
912+
// Numbers should be treated as costume indices, always
913+
if (name->isNaN() || name->isInfinity() || name->isNegativeInfinity())
914+
stage->setCostumeIndex(0);
915+
else
916+
setCostumeByIndex(stage, name->toLong() - 1);
917+
} else {
918+
// Strings should be treated as costume names, where possible
919+
const int costumeIndex = stage->findCostume(name->toString());
920+
std::string nameStr = name->toString();
921+
922+
auto it = std::find_if(nameStr.begin(), nameStr.end(), [](char c) { return !std::isspace(c); });
923+
bool isWhiteSpace = (it == nameStr.end());
924+
925+
if (costumeIndex != -1) {
926+
setCostumeByIndex(stage, costumeIndex);
927+
} else if (nameStr == "next backdrop") {
899928
nextBackdropImpl(vm);
900-
else if (nameStr == "previous backdrop")
929+
} else if (nameStr == "previous backdrop") {
901930
previousBackdropImpl(vm);
902-
else if (nameStr == "random backdrop") {
931+
} else if (nameStr == "random backdrop") {
903932
randomBackdropImpl(vm);
904-
} else {
905-
if (name->isValidNumber())
906-
setCostumeByIndex(stage, name->toLong() - 1);
933+
// Try to cast the string to a number (and treat it as a costume index)
934+
// Pure whitespace should not be treated as a number
935+
// Note: isNaN will cast the string to a number before checking if it's NaN
936+
} else if (!(name->isNaN() || isWhiteSpace)) {
937+
stage->setCostumeIndex(name->toInt() - 1);
907938
}
908-
} else
909-
setCostumeByIndex(stage, index);
939+
}
910940
}
911941

912942
void LooksBlocks::nextBackdropImpl(VirtualMachine *vm)

0 commit comments

Comments
 (0)