@@ -28,6 +28,8 @@ void SensingBlocks::registerBlocks(IEngine *engine)
2828{
2929 // Blocks
3030 engine->addCompileFunction (this , " sensing_distanceto" , &compileDistanceTo);
31+ engine->addCompileFunction (this , " sensing_askandwait" , &compileAskAndWait);
32+ engine->addCompileFunction (this , " sensing_answer" , &compileAnswer);
3133 engine->addCompileFunction (this , " sensing_keypressed" , &compileKeyPressed);
3234 engine->addCompileFunction (this , " sensing_mousedown" , &compileMouseDown);
3335 engine->addCompileFunction (this , " sensing_mousex" , &compileMouseX);
@@ -77,6 +79,9 @@ void SensingBlocks::registerBlocks(IEngine *engine)
7779 engine->addFieldValue (this , " background #" , BackdropNumber); // Scratch 1.4 support
7880 engine->addFieldValue (this , " backdrop #" , BackdropNumber);
7981 engine->addFieldValue (this , " backdrop name" , BackdropName);
82+
83+ // Callbacks
84+ engine->setQuestionAnswered (&onAnswer);
8085}
8186
8287void SensingBlocks::compileDistanceTo (Compiler *compiler)
@@ -100,6 +105,17 @@ void SensingBlocks::compileDistanceTo(Compiler *compiler)
100105 }
101106}
102107
108+ void SensingBlocks::compileAskAndWait (Compiler *compiler)
109+ {
110+ compiler->addInput (QUESTION);
111+ compiler->addFunctionCall (&askAndWait);
112+ }
113+
114+ void SensingBlocks::compileAnswer (Compiler *compiler)
115+ {
116+ compiler->addFunctionCall (&answer);
117+ }
118+
103119void SensingBlocks::compileKeyPressed (Compiler *compiler)
104120{
105121 compiler->addInput (KEY_OPTION);
@@ -488,6 +504,45 @@ unsigned int SensingBlocks::distanceToMousePointer(VirtualMachine *vm)
488504 return 0 ;
489505}
490506
507+ void SensingBlocks::onAnswer (const std::string &answer)
508+ {
509+ // https://github.com/scratchfoundation/scratch-vm/blob/6055823f203a696165084b873e661713806583ec/src/blocks/scratch3_sensing.js#L99-L115
510+ m_answer = answer;
511+
512+ if (!m_questionList.empty ()) {
513+ Question *question = m_questionList.front ().get ();
514+ VirtualMachine *vm = question->vm ;
515+ assert (vm);
516+ assert (vm->target ());
517+
518+ // If the target was visible when asked, hide the say bubble unless the target was the stage
519+ if (question->wasVisible && !question->wasStage )
520+ vm->target ()->setBubbleText (" " );
521+
522+ m_questionList.erase (m_questionList.begin ());
523+ vm->resolvePromise ();
524+ askNextQuestion ();
525+ }
526+ }
527+
528+ unsigned int SensingBlocks::askAndWait (VirtualMachine *vm)
529+ {
530+ const bool isQuestionAsked = !m_questionList.empty ();
531+ enqueueAsk (vm->getInput (0 , 1 )->toString (), vm);
532+
533+ if (!isQuestionAsked)
534+ askNextQuestion ();
535+
536+ vm->promise ();
537+ return 1 ;
538+ }
539+
540+ unsigned int SensingBlocks::answer (VirtualMachine *vm)
541+ {
542+ vm->addReturnValue (m_answer);
543+ return 0 ;
544+ }
545+
491546unsigned int SensingBlocks::timer (VirtualMachine *vm)
492547{
493548 vm->addReturnValue (vm->engine ()->timer ()->value ());
@@ -822,3 +877,44 @@ unsigned int SensingBlocks::daysSince2000(VirtualMachine *vm)
822877
823878 return 0 ;
824879}
880+
881+ void SensingBlocks::enqueueAsk (const std::string &question, VirtualMachine *vm)
882+ {
883+ // https://github.com/scratchfoundation/scratch-vm/blob/6055823f203a696165084b873e661713806583ec/src/blocks/scratch3_sensing.js#L117-L119
884+ assert (vm);
885+ Target *target = vm->target ();
886+ assert (target);
887+ bool visible = true ;
888+ bool isStage = target->isStage ();
889+
890+ if (!isStage) {
891+ Sprite *sprite = static_cast <Sprite *>(target);
892+ visible = sprite->visible ();
893+ }
894+
895+ m_questionList.push_back (std::make_unique<Question>(question, vm, visible, isStage));
896+ }
897+
898+ void SensingBlocks::askNextQuestion ()
899+ {
900+ // https://github.com/scratchfoundation/scratch-vm/blob/6055823f203a696165084b873e661713806583ec/src/blocks/scratch3_sensing.js#L121-L133
901+ if (m_questionList.empty ())
902+ return ;
903+
904+ Question *question = m_questionList.front ().get ();
905+ Target *target = question->vm ->target ();
906+ auto ask = question->vm ->engine ()->questionAsked ();
907+
908+ // If the target is visible, emit a blank question and show
909+ // a bubble unless the target was the stage
910+ if (question->wasVisible && !question->wasStage ) {
911+ target->setBubbleType (Target::BubbleType::Say);
912+ target->setBubbleText (question->question );
913+
914+ if (ask)
915+ ask (" " );
916+ } else {
917+ if (ask)
918+ ask (question->question );
919+ }
920+ }
0 commit comments