Skip to content

Commit 5730014

Browse files
committed
Load monitors from projects
1 parent 2270673 commit 5730014

File tree

3 files changed

+283
-1
lines changed

3 files changed

+283
-1
lines changed

src/internal/scratch3reader.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <scratchcpp/sound.h>
1313
#include <scratchcpp/stage.h>
1414
#include <scratchcpp/sprite.h>
15+
#include <scratchcpp/monitor.h>
1516

1617
#include "scratch3reader.h"
1718
#include "reader_common.h"
@@ -341,6 +342,107 @@ bool Scratch3Reader::load()
341342
m_targets.push_back(target);
342343
}
343344

345+
// monitors
346+
READER_STEP(step, "monitors");
347+
auto monitors = project["monitors"];
348+
349+
for (auto jsonMonitor : monitors) {
350+
READER_STEP(step, "monitor -> opcode");
351+
auto monitor = std::make_shared<Monitor>("", jsonMonitor["opcode"]);
352+
353+
// id
354+
READER_STEP(step, "monitor -> id");
355+
monitor->setId(jsonMonitor["id"]);
356+
357+
// mode
358+
READER_STEP(step, "monitor -> mode");
359+
auto mode = jsonMonitor["mode"];
360+
361+
if (mode == "default")
362+
monitor->setMode(Monitor::Mode::Default);
363+
else if (mode == "large")
364+
monitor->setMode(Monitor::Mode::Large);
365+
else if (mode == "slider")
366+
monitor->setMode(Monitor::Mode::Slider);
367+
else if (mode == "list")
368+
monitor->setMode(Monitor::Mode::List);
369+
else {
370+
printErr("unknown monitor mode: " + std::string(mode));
371+
return false;
372+
}
373+
374+
// params
375+
READER_STEP(step, "monitor -> params");
376+
377+
auto block = monitor->block();
378+
auto params = jsonMonitor["params"];
379+
380+
for (json::iterator it = params.begin(); it != params.end(); ++it) {
381+
auto field = std::make_shared<Field>(it.key(), jsonToValue(it.value()));
382+
block->addField(field);
383+
}
384+
385+
// spriteName
386+
READER_STEP(step, "monitor -> spriteName");
387+
388+
if (!jsonMonitor["spriteName"].is_null()) {
389+
std::string name = jsonMonitor["spriteName"];
390+
391+
for (auto target : m_targets) {
392+
if (!target->isStage()) {
393+
Sprite *sprite = dynamic_cast<Sprite *>(target.get());
394+
395+
if (sprite->name() == name) {
396+
monitor->setSprite(sprite);
397+
break;
398+
}
399+
}
400+
}
401+
402+
assert(monitor->sprite());
403+
}
404+
405+
// width
406+
READER_STEP(step, "monitor -> width");
407+
monitor->setWidth(jsonMonitor["width"]);
408+
409+
// height
410+
READER_STEP(step, "monitor -> height");
411+
monitor->setHeight(jsonMonitor["height"]);
412+
413+
// x
414+
READER_STEP(step, "monitor -> x");
415+
monitor->setX(jsonMonitor["x"]);
416+
417+
// y
418+
READER_STEP(step, "monitor -> y");
419+
monitor->setY(jsonMonitor["y"]);
420+
421+
// visible
422+
READER_STEP(step, "monitor -> visible");
423+
monitor->setVisible(jsonMonitor["visible"]);
424+
425+
// sliderMin
426+
READER_STEP(step, "monitor -> sliderMin");
427+
428+
if (jsonMonitor.contains("sliderMin"))
429+
monitor->setSliderMin(jsonMonitor["sliderMin"]);
430+
431+
// sliderMax
432+
READER_STEP(step, "monitor -> sliderMax");
433+
434+
if (jsonMonitor.contains("sliderMax"))
435+
monitor->setSliderMax(jsonMonitor["sliderMax"]);
436+
437+
// isDiscrete
438+
READER_STEP(step, "monitor -> isDiscrete");
439+
440+
if (jsonMonitor.contains("isDiscrete"))
441+
monitor->setDiscrete(jsonMonitor["isDiscrete"]);
442+
443+
m_monitors.push_back(monitor);
444+
}
445+
344446
// extensions
345447
READER_STEP(step, "extensions");
346448
auto extensions = project["extensions"];

test/load_project/load_project_test.cpp

Lines changed: 181 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <scratchcpp/inputvalue.h>
1414
#include <scratchcpp/comment.h>
1515
#include <scratchcpp/broadcast.h>
16+
#include <scratchcpp/monitor.h>
1617
#include <projectdownloaderfactorymock.h>
1718
#include <projectdownloadermock.h>
1819

@@ -205,7 +206,7 @@ TEST(LoadProjectTest, LoadTestProject)
205206
// Stage
206207
Stage *stage = engine->stage();
207208
ASSERT_EQ(stage->comments().size(), 1);
208-
ASSERT_EQ(stage->variables().size(), 2);
209+
ASSERT_EQ(stage->variables().size(), 4);
209210
ASSERT_EQ(stage->lists().size(), 1);
210211

211212
// Stage: comments
@@ -444,6 +445,185 @@ TEST(LoadProjectTest, LoadTestProject)
444445
ASSERT_LIST(sprite2, "list2");
445446
ASSERT_EQ(GET_LIST(sprite2, "list2")->toString(), "0 4 3 4 1 5 6 9 4 8");
446447

448+
// Monitors
449+
const auto &monitors = engine->monitors();
450+
ASSERT_EQ(monitors.size(), 11);
451+
452+
// list1
453+
auto monitor = monitors[0];
454+
ASSERT_EQ(monitor->id(), "/oB5:^t}UfL_Moa]OVbD");
455+
ASSERT_EQ(monitor->mode(), Monitor::Mode::List);
456+
ASSERT_EQ(monitor->opcode(), "data_listcontents");
457+
block = monitor->block();
458+
ASSERT_EQ(block->fields().size(), 1);
459+
auto field = block->fieldAt(0);
460+
ASSERT_EQ(field->name(), "LIST");
461+
ASSERT_EQ(field->value(), "list1");
462+
ASSERT_EQ(field->valuePtr(), GET_LIST(stage, "list1"));
463+
ASSERT_EQ(monitor->sprite(), nullptr);
464+
ASSERT_EQ(monitor->width(), 167);
465+
ASSERT_EQ(monitor->height(), 93);
466+
ASSERT_EQ(monitor->x(), 226);
467+
ASSERT_EQ(monitor->y(), 34);
468+
ASSERT_TRUE(monitor->visible());
469+
470+
// Sprite1: list2
471+
monitor = monitors[1];
472+
ASSERT_EQ(monitor->id(), "-!=?$nO,[RI{7!^_:x=?");
473+
ASSERT_EQ(monitor->mode(), Monitor::Mode::List);
474+
ASSERT_EQ(monitor->opcode(), "data_listcontents");
475+
block = monitor->block();
476+
ASSERT_EQ(block->fields().size(), 1);
477+
field = block->fieldAt(0);
478+
ASSERT_EQ(field->name(), "LIST");
479+
ASSERT_EQ(field->value(), "list2");
480+
ASSERT_EQ(field->valuePtr(), GET_LIST(engine->targetAt(engine->findTarget("Sprite1")), "list2"));
481+
ASSERT_EQ(monitor->sprite(), dynamic_cast<Sprite *>(engine->targetAt(engine->findTarget("Sprite1"))));
482+
ASSERT_EQ(monitor->width(), 0);
483+
ASSERT_EQ(monitor->height(), 0);
484+
ASSERT_EQ(monitor->x(), 106);
485+
ASSERT_EQ(monitor->y(), 5);
486+
ASSERT_TRUE(monitor->visible());
487+
488+
// Balloon1: list2
489+
monitor = monitors[2];
490+
ASSERT_EQ(monitor->id(), "$FebBLy/KiSa19@:b-iA");
491+
ASSERT_EQ(monitor->mode(), Monitor::Mode::List);
492+
ASSERT_EQ(monitor->opcode(), "data_listcontents");
493+
block = monitor->block();
494+
ASSERT_EQ(block->fields().size(), 1);
495+
field = block->fieldAt(0);
496+
ASSERT_EQ(field->name(), "LIST");
497+
ASSERT_EQ(field->value(), "list2");
498+
ASSERT_EQ(field->valuePtr(), GET_LIST(engine->targetAt(engine->findTarget("Balloon1")), "list2"));
499+
ASSERT_EQ(monitor->sprite(), dynamic_cast<Sprite *>(engine->targetAt(engine->findTarget("Balloon1"))));
500+
ASSERT_EQ(monitor->width(), 0);
501+
ASSERT_EQ(monitor->height(), 0);
502+
ASSERT_EQ(monitor->x(), 255);
503+
ASSERT_EQ(monitor->y(), 5);
504+
ASSERT_FALSE(monitor->visible());
505+
506+
// var1
507+
monitor = monitors[3];
508+
ASSERT_EQ(monitor->id(), "`jEk@4|i[#Fk?(8x)AV.-my variable");
509+
ASSERT_EQ(monitor->mode(), Monitor::Mode::Default);
510+
ASSERT_EQ(monitor->opcode(), "data_variable");
511+
block = monitor->block();
512+
ASSERT_EQ(block->fields().size(), 1);
513+
field = block->fieldAt(0);
514+
ASSERT_EQ(field->name(), "VARIABLE");
515+
ASSERT_EQ(field->value(), "var1");
516+
ASSERT_EQ(field->valuePtr(), GET_VAR(stage, "var1"));
517+
ASSERT_EQ(monitor->sprite(), nullptr);
518+
ASSERT_EQ(monitor->width(), 0);
519+
ASSERT_EQ(monitor->height(), 0);
520+
ASSERT_EQ(monitor->x(), 5);
521+
ASSERT_EQ(monitor->y(), 212);
522+
ASSERT_TRUE(monitor->visible());
523+
524+
// Sprite1: var2
525+
monitor = monitors[4];
526+
ASSERT_EQ(monitor->id(), "eN~@jd#CfxXM(wA6qcyt");
527+
ASSERT_EQ(monitor->mode(), Monitor::Mode::Default);
528+
ASSERT_EQ(monitor->opcode(), "data_variable");
529+
block = monitor->block();
530+
ASSERT_EQ(block->fields().size(), 1);
531+
field = block->fieldAt(0);
532+
ASSERT_EQ(field->name(), "VARIABLE");
533+
ASSERT_EQ(field->value(), "var2");
534+
ASSERT_EQ(field->valuePtr(), GET_VAR(engine->targetAt(engine->findTarget("Sprite1")), "var2"));
535+
ASSERT_EQ(monitor->sprite(), dynamic_cast<Sprite *>(engine->targetAt(engine->findTarget("Sprite1"))));
536+
ASSERT_EQ(monitor->width(), 0);
537+
ASSERT_EQ(monitor->height(), 0);
538+
ASSERT_EQ(monitor->x(), 5);
539+
ASSERT_EQ(monitor->y(), 212);
540+
ASSERT_FALSE(monitor->visible());
541+
542+
// Balloon1: var2
543+
monitor = monitors[5];
544+
ASSERT_EQ(monitor->id(), "g2][rYmi~u[wE@o$jckr");
545+
ASSERT_EQ(monitor->mode(), Monitor::Mode::Large);
546+
ASSERT_EQ(monitor->opcode(), "data_variable");
547+
block = monitor->block();
548+
ASSERT_EQ(block->fields().size(), 1);
549+
field = block->fieldAt(0);
550+
ASSERT_EQ(field->name(), "VARIABLE");
551+
ASSERT_EQ(field->value(), "var2");
552+
ASSERT_EQ(field->valuePtr(), GET_VAR(engine->targetAt(engine->findTarget("Balloon1")), "var2"));
553+
ASSERT_EQ(monitor->sprite(), dynamic_cast<Sprite *>(engine->targetAt(engine->findTarget("Balloon1"))));
554+
ASSERT_EQ(monitor->width(), 0);
555+
ASSERT_EQ(monitor->height(), 0);
556+
ASSERT_EQ(monitor->x(), 146);
557+
ASSERT_EQ(monitor->y(), 267);
558+
ASSERT_TRUE(monitor->visible());
559+
560+
// loudness
561+
monitor = monitors[6];
562+
ASSERT_EQ(monitor->id(), "loudness");
563+
ASSERT_EQ(monitor->mode(), Monitor::Mode::Default);
564+
ASSERT_EQ(monitor->opcode(), "sensing_loudness");
565+
block = monitor->block();
566+
ASSERT_TRUE(block->fields().empty());
567+
ASSERT_EQ(monitor->sprite(), nullptr);
568+
ASSERT_EQ(monitor->width(), 0);
569+
ASSERT_EQ(monitor->height(), 0);
570+
ASSERT_EQ(monitor->x(), 5);
571+
ASSERT_EQ(monitor->y(), 239);
572+
ASSERT_TRUE(monitor->visible());
573+
574+
// current year
575+
monitor = monitors[7];
576+
ASSERT_EQ(monitor->id(), "current_year");
577+
ASSERT_EQ(monitor->mode(), Monitor::Mode::Default);
578+
ASSERT_EQ(monitor->opcode(), "sensing_current");
579+
block = monitor->block();
580+
ASSERT_EQ(block->fields().size(), 1);
581+
field = block->fieldAt(0);
582+
ASSERT_EQ(field->name(), "CURRENTMENU");
583+
ASSERT_EQ(field->value(), "YEAR");
584+
ASSERT_EQ(monitor->sprite(), nullptr);
585+
ASSERT_EQ(monitor->width(), 0);
586+
ASSERT_EQ(monitor->height(), 0);
587+
ASSERT_EQ(monitor->x(), 5);
588+
ASSERT_EQ(monitor->y(), 5);
589+
ASSERT_TRUE(monitor->visible());
590+
591+
// var4
592+
monitor = monitors[8];
593+
ASSERT_EQ(monitor->id(), "k^cUO5^Pcq!9lY|dxlg+");
594+
ASSERT_EQ(monitor->mode(), Monitor::Mode::Slider);
595+
ASSERT_EQ(monitor->opcode(), "data_variable");
596+
block = monitor->block();
597+
ASSERT_EQ(block->fields().size(), 1);
598+
field = block->fieldAt(0);
599+
ASSERT_EQ(field->name(), "VARIABLE");
600+
ASSERT_EQ(field->value(), "var4");
601+
ASSERT_EQ(field->valuePtr(), GET_VAR(stage, "var4"));
602+
ASSERT_EQ(monitor->sprite(), nullptr);
603+
ASSERT_EQ(monitor->width(), 0);
604+
ASSERT_EQ(monitor->height(), 0);
605+
ASSERT_EQ(monitor->x(), 305);
606+
ASSERT_EQ(monitor->y(), 234);
607+
ASSERT_TRUE(monitor->visible());
608+
609+
// var5
610+
monitor = monitors[9];
611+
ASSERT_EQ(monitor->id(), "lWC9K6_lG+vq!)EX}npr");
612+
ASSERT_EQ(monitor->mode(), Monitor::Mode::Slider);
613+
ASSERT_EQ(monitor->opcode(), "data_variable");
614+
block = monitor->block();
615+
ASSERT_EQ(block->fields().size(), 1);
616+
field = block->fieldAt(0);
617+
ASSERT_EQ(field->name(), "VARIABLE");
618+
ASSERT_EQ(field->value(), "var5");
619+
ASSERT_EQ(field->valuePtr(), GET_VAR(stage, "var5"));
620+
ASSERT_EQ(monitor->sprite(), nullptr);
621+
ASSERT_EQ(monitor->width(), 0);
622+
ASSERT_EQ(monitor->height(), 0);
623+
ASSERT_EQ(monitor->x(), 304);
624+
ASSERT_EQ(monitor->y(), 280);
625+
ASSERT_TRUE(monitor->visible());
626+
447627
i++;
448628
}
449629
}

test/load_test.sb3

201 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)