1212
1313#include " looksblocks.h"
1414#include " ../engine/internal/randomgenerator.h"
15+ #include " ../engine/internal/clock.h"
1516
1617using namespace libscratchcpp ;
1718
1819IRandomGenerator *LooksBlocks::rng = nullptr ;
20+ IClock *LooksBlocks::clock = nullptr ;
1921
2022std::string LooksBlocks::name () const
2123{
@@ -25,6 +27,10 @@ std::string LooksBlocks::name() const
2527void LooksBlocks::registerBlocks (IEngine *engine)
2628{
2729 // Blocks
30+ engine->addCompileFunction (this , " looks_sayforsecs" , &compileSayForSecs);
31+ engine->addCompileFunction (this , " looks_say" , &compileSay);
32+ engine->addCompileFunction (this , " looks_thinkforsecs" , &compileThinkForSecs);
33+ engine->addCompileFunction (this , " looks_think" , &compileThink);
2834 engine->addCompileFunction (this , " looks_show" , &compileShow);
2935 engine->addCompileFunction (this , " looks_hide" , &compileHide);
3036 engine->addCompileFunction (this , " looks_changeeffectby" , &compileChangeEffectBy);
@@ -49,6 +55,8 @@ void LooksBlocks::registerBlocks(IEngine *engine)
4955 engine->addMonitorNameFunction (this , " looks_size" , &sizeMonitorName);
5056
5157 // Inputs
58+ engine->addInput (this , " MESSAGE" , MESSAGE);
59+ engine->addInput (this , " SECS" , SECS);
5260 engine->addInput (this , " CHANGE" , CHANGE);
5361 engine->addInput (this , " SIZE" , SIZE);
5462 engine->addInput (this , " COSTUME" , COSTUME);
@@ -77,6 +85,34 @@ void LooksBlocks::registerBlocks(IEngine *engine)
7785 engine->addFieldValue (this , " backward" , Backward);
7886}
7987
88+ void LooksBlocks::compileSayForSecs (Compiler *compiler)
89+ {
90+ compiler->addInput (MESSAGE);
91+ compiler->addInput (SECS);
92+ compiler->addFunctionCall (&startSayForSecs);
93+ compiler->addFunctionCall (&sayForSecs);
94+ }
95+
96+ void LooksBlocks::compileSay (Compiler *compiler)
97+ {
98+ compiler->addInput (MESSAGE);
99+ compiler->addFunctionCall (&say);
100+ }
101+
102+ void LooksBlocks::compileThinkForSecs (Compiler *compiler)
103+ {
104+ compiler->addInput (MESSAGE);
105+ compiler->addInput (SECS);
106+ compiler->addFunctionCall (&startThinkForSecs);
107+ compiler->addFunctionCall (&thinkForSecs);
108+ }
109+
110+ void LooksBlocks::compileThink (Compiler *compiler)
111+ {
112+ compiler->addInput (MESSAGE);
113+ compiler->addFunctionCall (&think);
114+ }
115+
80116void LooksBlocks::compileShow (Compiler *compiler)
81117{
82118 compiler->addFunctionCall (&show);
@@ -515,6 +551,114 @@ const std::string &LooksBlocks::sizeMonitorName(Block *block)
515551 return name;
516552}
517553
554+ void LooksBlocks::startWait (VirtualMachine *vm, double secs)
555+ {
556+ if (!clock)
557+ clock = Clock::instance ().get ();
558+
559+ auto currentTime = clock->currentSteadyTime ();
560+ m_timeMap[vm] = { currentTime, secs * 1000 };
561+ vm->engine ()->requestRedraw ();
562+ }
563+
564+ bool LooksBlocks::wait (VirtualMachine *vm)
565+ {
566+ if (!clock)
567+ clock = Clock::instance ().get ();
568+
569+ auto currentTime = clock->currentSteadyTime ();
570+ assert (m_timeMap.count (vm) == 1 );
571+
572+ if (std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - m_timeMap[vm].first ).count () >= m_timeMap[vm].second ) {
573+ m_timeMap.erase (vm);
574+ vm->stop (true , true , false );
575+ return true ;
576+ } else {
577+ vm->stop (true , true , true );
578+ return false ;
579+ }
580+ }
581+
582+ void LooksBlocks::showBubble (VirtualMachine *vm, Target::BubbleType type, const std::string &text)
583+ {
584+ Target *target = vm->target ();
585+
586+ if (target) {
587+ target->setBubbleType (type);
588+ target->setBubbleText (text);
589+ m_waitingBubbles.erase (target);
590+ }
591+ }
592+
593+ void LooksBlocks::hideBubble (Target *target)
594+ {
595+ if (!target)
596+ return ;
597+
598+ target->setBubbleText (" " );
599+ m_waitingBubbles.erase (target);
600+ }
601+
602+ unsigned int LooksBlocks::startSayForSecs (VirtualMachine *vm)
603+ {
604+ Target *target = vm->target ();
605+
606+ if (target) {
607+ showBubble (vm, Target::BubbleType::Say, vm->getInput (0 , 2 )->toString ());
608+ m_waitingBubbles[target] = vm;
609+ startWait (vm, vm->getInput (1 , 2 )->toDouble ());
610+ }
611+
612+ return 2 ;
613+ }
614+
615+ unsigned int LooksBlocks::sayForSecs (VirtualMachine *vm)
616+ {
617+ if (wait (vm)) {
618+ Target *target = vm->target ();
619+
620+ if (target) {
621+ auto it = m_waitingBubbles.find (target);
622+
623+ // Clear bubble if it hasn't been changed
624+ if (it != m_waitingBubbles.cend () && it->second == vm)
625+ hideBubble (vm->target ());
626+ }
627+ }
628+
629+ return 0 ;
630+ }
631+
632+ unsigned int LooksBlocks::say (VirtualMachine *vm)
633+ {
634+ showBubble (vm, Target::BubbleType::Say, vm->getInput (0 , 1 )->toString ());
635+ return 1 ;
636+ }
637+
638+ unsigned int LooksBlocks::startThinkForSecs (VirtualMachine *vm)
639+ {
640+ Target *target = vm->target ();
641+
642+ if (target) {
643+ showBubble (vm, Target::BubbleType::Think, vm->getInput (0 , 2 )->toString ());
644+ m_waitingBubbles[target] = vm;
645+ startWait (vm, vm->getInput (1 , 2 )->toDouble ());
646+ }
647+
648+ return 2 ;
649+ }
650+
651+ unsigned int LooksBlocks::thinkForSecs (VirtualMachine *vm)
652+ {
653+ return sayForSecs (vm); // there isn't any difference
654+ }
655+
656+ unsigned int LooksBlocks::think (VirtualMachine *vm)
657+ {
658+ showBubble (vm, Target::BubbleType::Think, vm->getInput (0 , 1 )->toString ());
659+ return 1 ;
660+ }
661+
518662unsigned int LooksBlocks::show (VirtualMachine *vm)
519663{
520664 Sprite *sprite = dynamic_cast <Sprite *>(vm->target ());
0 commit comments