Skip to content

Commit c97a871

Browse files
authored
Merge pull request #466 from scratchcpp/say_think_blocks
Implement say and think blocks
2 parents 1cb6a63 + 30d945b commit c97a871

File tree

3 files changed

+591
-1
lines changed

3 files changed

+591
-1
lines changed

src/blocks/looksblocks.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212

1313
#include "looksblocks.h"
1414
#include "../engine/internal/randomgenerator.h"
15+
#include "../engine/internal/clock.h"
1516

1617
using namespace libscratchcpp;
1718

1819
IRandomGenerator *LooksBlocks::rng = nullptr;
20+
IClock *LooksBlocks::clock = nullptr;
1921

2022
std::string LooksBlocks::name() const
2123
{
@@ -25,6 +27,10 @@ std::string LooksBlocks::name() const
2527
void 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+
80116
void 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+
518662
unsigned int LooksBlocks::show(VirtualMachine *vm)
519663
{
520664
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());

src/blocks/looksblocks.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,28 @@
33
#pragma once
44

55
#include <scratchcpp/iblocksection.h>
6+
#include <scratchcpp/target.h>
67
#include <vector>
8+
#include <unordered_map>
9+
#include <chrono>
710

811
namespace libscratchcpp
912
{
1013

11-
class Target;
1214
class Stage;
1315
class Value;
1416
class IGraphicsEffect;
1517
class IRandomGenerator;
18+
class IClock;
1619

1720
/*! \brief The LooksBlocks class contains the implementation of looks blocks. */
1821
class LooksBlocks : public IBlockSection
1922
{
2023
public:
2124
enum Inputs
2225
{
26+
MESSAGE,
27+
SECS,
2328
CHANGE,
2429
SIZE,
2530
COSTUME,
@@ -57,6 +62,10 @@ class LooksBlocks : public IBlockSection
5762

5863
void registerBlocks(IEngine *engine) override;
5964

65+
static void compileSayForSecs(Compiler *compiler);
66+
static void compileSay(Compiler *compiler);
67+
static void compileThinkForSecs(Compiler *compiler);
68+
static void compileThink(Compiler *compiler);
6069
static void compileShow(Compiler *compiler);
6170
static void compileHide(Compiler *compiler);
6271
static void compileChangeEffectBy(Compiler *compiler);
@@ -79,6 +88,19 @@ class LooksBlocks : public IBlockSection
7988
static const std::string &backdropNumberNameMonitorName(Block *block);
8089
static const std::string &sizeMonitorName(Block *block);
8190

91+
static void startWait(VirtualMachine *vm, double secs);
92+
static bool wait(VirtualMachine *vm);
93+
static void showBubble(VirtualMachine *vm, Target::BubbleType type, const std::string &text);
94+
static void hideBubble(Target *target);
95+
96+
static unsigned int startSayForSecs(VirtualMachine *vm);
97+
static unsigned int sayForSecs(VirtualMachine *vm);
98+
static unsigned int say(VirtualMachine *vm);
99+
100+
static unsigned int startThinkForSecs(VirtualMachine *vm);
101+
static unsigned int thinkForSecs(VirtualMachine *vm);
102+
static unsigned int think(VirtualMachine *vm);
103+
82104
static unsigned int show(VirtualMachine *vm);
83105
static unsigned int hide(VirtualMachine *vm);
84106

@@ -141,6 +163,9 @@ class LooksBlocks : public IBlockSection
141163
static unsigned int backdropNumber(VirtualMachine *vm);
142164
static unsigned int backdropName(VirtualMachine *vm);
143165

166+
static inline std::unordered_map<VirtualMachine *, std::pair<std::chrono::steady_clock::time_point, int>> m_timeMap;
167+
static inline std::unordered_map<Target *, VirtualMachine *> m_waitingBubbles;
168+
144169
static inline std::vector<IGraphicsEffect *> m_customGraphicsEffects;
145170
static inline IGraphicsEffect *m_colorEffect = nullptr;
146171
static inline IGraphicsEffect *m_fisheyeEffect = nullptr;
@@ -151,6 +176,7 @@ class LooksBlocks : public IBlockSection
151176
static inline IGraphicsEffect *m_ghostEffect = nullptr;
152177

153178
static IRandomGenerator *rng;
179+
static IClock *clock;
154180
};
155181

156182
} // namespace libscratchcpp

0 commit comments

Comments
 (0)