Skip to content

Commit f74e244

Browse files
authored
Merge pull request #572 from scratchcpp/switch_costume_behavior
Fix #522: Fix switch costume/backdrop behavior
2 parents ba14cf8 + 8c473d0 commit f74e244

File tree

3 files changed

+399
-909
lines changed

3 files changed

+399
-909
lines changed

src/blocks/looksblocks.cpp

Lines changed: 57 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -347,36 +347,8 @@ void LooksBlocks::compileSwitchCostumeTo(Compiler *compiler)
347347
if (!target)
348348
return;
349349

350-
Input *input = compiler->input(COSTUME);
351-
352-
if (input->pointsToDropdownMenu()) {
353-
std::string value = input->selectedMenuItem();
354-
int index = target->findCostume(value);
355-
356-
if (index == -1) {
357-
if (value == "next costume")
358-
compiler->addFunctionCall(&nextCostume);
359-
else if (value == "previous costume")
360-
compiler->addFunctionCall(&previousCostume);
361-
else {
362-
Value v(value);
363-
364-
if (v.type() == Value::Type::Integer) {
365-
compiler->addConstValue(v.toLong() - 1);
366-
compiler->addFunctionCall(&switchCostumeToByIndex);
367-
} else {
368-
compiler->addInput(input);
369-
compiler->addFunctionCall(&switchCostumeTo);
370-
}
371-
}
372-
} else {
373-
compiler->addConstValue(index);
374-
compiler->addFunctionCall(&switchCostumeToByIndex);
375-
}
376-
} else {
377-
compiler->addInput(input);
378-
compiler->addFunctionCall(&switchCostumeTo);
379-
}
350+
compiler->addInput(COSTUME);
351+
compiler->addFunctionCall(&switchCostumeTo);
380352
}
381353

382354
void LooksBlocks::compileNextCostume(Compiler *compiler)
@@ -386,85 +358,14 @@ void LooksBlocks::compileNextCostume(Compiler *compiler)
386358

387359
void LooksBlocks::compileSwitchBackdropTo(Compiler *compiler)
388360
{
389-
Stage *stage = compiler->engine()->stage();
390-
391-
if (!stage)
392-
return;
393-
394-
Input *input = compiler->input(BACKDROP);
395-
396-
if (input->pointsToDropdownMenu()) {
397-
std::string value = input->selectedMenuItem();
398-
int index = stage->findCostume(value);
399-
400-
if (index == -1) {
401-
if (value == "next backdrop")
402-
compiler->addFunctionCall(&nextBackdrop);
403-
else if (value == "previous backdrop")
404-
compiler->addFunctionCall(&previousBackdrop);
405-
else if (value == "random backdrop")
406-
compiler->addFunctionCall(&randomBackdrop);
407-
else {
408-
Value v(value);
409-
410-
if (v.type() == Value::Type::Integer) {
411-
compiler->addConstValue(v.toLong() - 1);
412-
compiler->addFunctionCall(&switchBackdropToByIndex);
413-
} else {
414-
compiler->addInput(input);
415-
compiler->addFunctionCall(&switchBackdropTo);
416-
}
417-
}
418-
} else {
419-
compiler->addConstValue(index);
420-
compiler->addFunctionCall(&switchBackdropToByIndex);
421-
}
422-
} else {
423-
compiler->addInput(input);
424-
compiler->addFunctionCall(&switchBackdropTo);
425-
}
361+
compiler->addInput(BACKDROP);
362+
compiler->addFunctionCall(&switchBackdropTo);
426363
}
427364

428365
void LooksBlocks::compileSwitchBackdropToAndWait(Compiler *compiler)
429366
{
430-
Stage *stage = compiler->engine()->stage();
431-
432-
if (!stage)
433-
return;
434-
435-
Input *input = compiler->input(BACKDROP);
436-
437-
if (input->pointsToDropdownMenu()) {
438-
std::string value = input->selectedMenuItem();
439-
int index = stage->findCostume(value);
440-
441-
if (index == -1) {
442-
if (value == "next backdrop")
443-
compiler->addFunctionCall(&nextBackdropAndWait);
444-
else if (value == "previous backdrop")
445-
compiler->addFunctionCall(&previousBackdropAndWait);
446-
else if (value == "random backdrop")
447-
compiler->addFunctionCall(&randomBackdropAndWait);
448-
else {
449-
Value v(value);
450-
451-
if (v.type() == Value::Type::Integer) {
452-
compiler->addConstValue(v.toLong() - 1);
453-
compiler->addFunctionCall(&switchBackdropToByIndexAndWait);
454-
} else {
455-
compiler->addInput(input);
456-
compiler->addFunctionCall(&switchBackdropToAndWait);
457-
}
458-
}
459-
} else {
460-
compiler->addConstValue(index);
461-
compiler->addFunctionCall(&switchBackdropToByIndexAndWait);
462-
}
463-
} else {
464-
compiler->addInput(input);
465-
compiler->addFunctionCall(&switchBackdropToAndWait);
466-
}
467-
367+
compiler->addInput(BACKDROP);
368+
compiler->addFunctionCall(&switchBackdropToAndWait);
468369
compiler->addFunctionCall(&backdropNumber);
469370
compiler->addFunctionCall(&checkBackdropScripts);
470371
}
@@ -932,36 +833,43 @@ void LooksBlocks::setCostumeByIndex(Target *target, long index)
932833
target->setCostumeIndex(index);
933834
}
934835

935-
unsigned int LooksBlocks::switchCostumeToByIndex(VirtualMachine *vm)
936-
{
937-
if (Target *target = vm->target())
938-
setCostumeByIndex(target, vm->getInput(0, 1)->toLong());
939-
940-
return 1;
941-
}
942-
943836
unsigned int LooksBlocks::switchCostumeTo(VirtualMachine *vm)
944837
{
838+
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L389-L413
945839
Target *target = vm->target();
946840

947841
if (!target)
948842
return 1;
949843

950844
const Value *name = vm->getInput(0, 1);
951-
std::string nameStr = name->toString();
952-
int index = target->findCostume(nameStr);
953845

954-
if (index == -1) {
955-
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") {
956863
nextCostume(vm);
957-
else if (nameStr == "previous costume")
864+
} else if (nameStr == "previous costume") {
958865
previousCostume(vm);
959-
else {
960-
if (name->isValidNumber())
961-
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);
962871
}
963-
} else
964-
setCostumeByIndex(target, index);
872+
}
965873

966874
return 1;
967875
}
@@ -990,36 +898,45 @@ void LooksBlocks::startBackdropScripts(VirtualMachine *vm, bool wait)
990898
}
991899
}
992900

993-
void LooksBlocks::switchBackdropToByIndexImpl(VirtualMachine *vm)
994-
{
995-
if (Stage *stage = vm->engine()->stage())
996-
setCostumeByIndex(stage, vm->getInput(0, 1)->toLong());
997-
}
998-
999901
void LooksBlocks::switchBackdropToImpl(VirtualMachine *vm)
1000902
{
903+
// https://github.com/scratchfoundation/scratch-vm/blob/8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c/src/blocks/scratch3_looks.js#L423-L462
1001904
Stage *stage = vm->engine()->stage();
1002905

1003906
if (!stage)
1004907
return;
1005908

1006909
const Value *name = vm->getInput(0, 1);
1007-
std::string nameStr = name->toString();
1008-
int index = stage->findCostume(nameStr);
1009910

1010-
if (index == -1) {
1011-
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") {
1012928
nextBackdropImpl(vm);
1013-
else if (nameStr == "previous backdrop")
929+
} else if (nameStr == "previous backdrop") {
1014930
previousBackdropImpl(vm);
1015-
else if (nameStr == "random backdrop") {
931+
} else if (nameStr == "random backdrop") {
1016932
randomBackdropImpl(vm);
1017-
} else {
1018-
if (name->isValidNumber())
1019-
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);
1020938
}
1021-
} else
1022-
setCostumeByIndex(stage, index);
939+
}
1023940
}
1024941

1025942
void LooksBlocks::nextBackdropImpl(VirtualMachine *vm)
@@ -1047,14 +964,6 @@ void LooksBlocks::randomBackdropImpl(VirtualMachine *vm)
1047964
}
1048965
}
1049966

1050-
unsigned int LooksBlocks::switchBackdropToByIndex(VirtualMachine *vm)
1051-
{
1052-
switchBackdropToByIndexImpl(vm);
1053-
startBackdropScripts(vm, false);
1054-
1055-
return 1;
1056-
}
1057-
1058967
unsigned int LooksBlocks::switchBackdropTo(VirtualMachine *vm)
1059968
{
1060969
switchBackdropToImpl(vm);
@@ -1063,14 +972,6 @@ unsigned int LooksBlocks::switchBackdropTo(VirtualMachine *vm)
1063972
return 1;
1064973
}
1065974

1066-
unsigned int LooksBlocks::switchBackdropToByIndexAndWait(VirtualMachine *vm)
1067-
{
1068-
switchBackdropToByIndexImpl(vm);
1069-
startBackdropScripts(vm, true);
1070-
1071-
return 1;
1072-
}
1073-
1074975
unsigned int LooksBlocks::switchBackdropToAndWait(VirtualMachine *vm)
1075976
{
1076977
switchBackdropToImpl(vm);

src/blocks/looksblocks.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,21 +129,17 @@ class LooksBlocks : public IBlockSection
129129
static unsigned int size(VirtualMachine *vm);
130130

131131
static void setCostumeByIndex(Target *target, long index);
132-
static unsigned int switchCostumeToByIndex(VirtualMachine *vm);
133132
static unsigned int switchCostumeTo(VirtualMachine *vm);
134133
static unsigned int nextCostume(VirtualMachine *vm);
135134
static unsigned int previousCostume(VirtualMachine *vm);
136135

137136
static void startBackdropScripts(VirtualMachine *vm, bool wait);
138-
static void switchBackdropToByIndexImpl(VirtualMachine *vm);
139137
static void switchBackdropToImpl(VirtualMachine *vm);
140138
static void nextBackdropImpl(VirtualMachine *vm);
141139
static void previousBackdropImpl(VirtualMachine *vm);
142140
static void randomBackdropImpl(VirtualMachine *vm);
143141

144-
static unsigned int switchBackdropToByIndex(VirtualMachine *vm);
145142
static unsigned int switchBackdropTo(VirtualMachine *vm);
146-
static unsigned int switchBackdropToByIndexAndWait(VirtualMachine *vm);
147143
static unsigned int switchBackdropToAndWait(VirtualMachine *vm);
148144
static unsigned int nextBackdrop(VirtualMachine *vm);
149145
static unsigned int nextBackdropAndWait(VirtualMachine *vm);

0 commit comments

Comments
 (0)