Skip to content

Commit 096e5d8

Browse files
committed
Implement event_whengreaterthan block
1 parent 7a10ac0 commit 096e5d8

File tree

9 files changed

+291
-9
lines changed

9 files changed

+291
-9
lines changed

include/scratchcpp/iengine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ class LIBSCRATCHCPP_EXPORT IEngine
299299
/* Registers the given "when this sprite/stage clicked" script. */
300300
virtual void addTargetClickScript(std::shared_ptr<Block> hatBlock) = 0;
301301

302+
/* Registers the given "when greater than" script. */
303+
virtual void addWhenGreaterThanScript(std::shared_ptr<Block> hatBlock) = 0;
304+
302305
/*! Returns the list of targets. */
303306
virtual const std::vector<std::shared_ptr<Target>> &targets() const = 0;
304307

src/blocks/eventblocks.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@
88
#include <scratchcpp/field.h>
99
#include <scratchcpp/stage.h>
1010
#include <scratchcpp/costume.h>
11+
#include <scratchcpp/block.h>
12+
#include <scratchcpp/itimer.h>
1113

1214
#include "eventblocks.h"
15+
#include "audio/audioinput.h"
16+
#include "audio/iaudioloudness.h"
1317

1418
using namespace libscratchcpp;
1519

20+
IAudioInput *EventBlocks::audioInput = nullptr;
21+
1622
std::string EventBlocks::name() const
1723
{
1824
return "Events";
@@ -28,15 +34,25 @@ void EventBlocks::registerBlocks(IEngine *engine)
2834
engine->addCompileFunction(this, "event_broadcastandwait", &compileBroadcastAndWait);
2935
engine->addCompileFunction(this, "event_whenbroadcastreceived", &compileWhenBroadcastReceived);
3036
engine->addCompileFunction(this, "event_whenbackdropswitchesto", &compileWhenBackdropSwitchesTo);
37+
engine->addCompileFunction(this, "event_whengreaterthan", &compileWhenGreaterThan);
3138
engine->addCompileFunction(this, "event_whenkeypressed", &compileWhenKeyPressed);
3239

40+
// Hat predicates
41+
engine->addHatPredicateCompileFunction(this, "event_whengreaterthan", &compileWhenGreaterThanPredicate);
42+
3343
// Inputs
3444
engine->addInput(this, "BROADCAST_INPUT", BROADCAST_INPUT);
45+
engine->addInput(this, "VALUE", VALUE);
3546

3647
// Fields
3748
engine->addField(this, "BROADCAST_OPTION", BROADCAST_OPTION);
3849
engine->addField(this, "BACKDROP", BACKDROP);
50+
engine->addField(this, "WHENGREATERTHANMENU", WHENGREATERTHANMENU);
3951
engine->addField(this, "KEY_OPTION", KEY_OPTION);
52+
53+
// Fields values
54+
engine->addFieldValue(this, "LOUDNESS", Loudness);
55+
engine->addFieldValue(this, "TIMER", Timer);
4056
}
4157

4258
void EventBlocks::compileWhenFlagClicked(Compiler *compiler)
@@ -97,6 +113,38 @@ void EventBlocks::compileWhenBackdropSwitchesTo(Compiler *compiler)
97113
compiler->engine()->addBackdropChangeScript(compiler->block(), BACKDROP);
98114
}
99115

116+
void EventBlocks::compileWhenGreaterThanPredicate(Compiler *compiler)
117+
{
118+
Field *field = compiler->field(WHENGREATERTHANMENU);
119+
BlockFunc predicate = nullptr;
120+
121+
if (field) {
122+
switch (field->specialValueId()) {
123+
case Loudness:
124+
predicate = &whenLoudnessGreaterThanPredicate;
125+
break;
126+
127+
case Timer:
128+
predicate = &whenTimerGreaterThanPredicate;
129+
break;
130+
131+
default:
132+
compiler->addInstruction(vm::OP_NULL);
133+
return;
134+
}
135+
}
136+
137+
if (predicate) {
138+
compiler->addInput(VALUE);
139+
compiler->addFunctionCall(predicate);
140+
}
141+
}
142+
143+
void EventBlocks::compileWhenGreaterThan(Compiler *compiler)
144+
{
145+
compiler->engine()->addWhenGreaterThanScript(compiler->block());
146+
}
147+
100148
void EventBlocks::compileWhenKeyPressed(Compiler *compiler)
101149
{
102150
// NOTE: Field values don't have to be registered because keys are referenced by their names
@@ -140,3 +188,21 @@ unsigned int EventBlocks::checkBroadcastByIndex(VirtualMachine *vm)
140188
vm->stop(true, true, true);
141189
return 1;
142190
}
191+
192+
unsigned int EventBlocks::whenLoudnessGreaterThanPredicate(VirtualMachine *vm)
193+
{
194+
if (!audioInput)
195+
audioInput = AudioInput::instance().get();
196+
197+
auto audioLoudness = audioInput->audioLoudness();
198+
const Value &operand = *vm->getInput(0, 1);
199+
vm->replaceReturnValue(Value(audioLoudness->getLoudness()) > operand, 1);
200+
return 0;
201+
}
202+
203+
unsigned int EventBlocks::whenTimerGreaterThanPredicate(VirtualMachine *vm)
204+
{
205+
const Value &operand = *vm->getInput(0, 1);
206+
vm->replaceReturnValue(Value(vm->engine()->timer()->value()) > operand, 1);
207+
return 0;
208+
}

src/blocks/eventblocks.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,32 @@ namespace libscratchcpp
99

1010
class Compiler;
1111
class VirtualMachine;
12+
class IAudioInput;
1213

1314
/*! \brief The EventBlocks class contains the implementation of event blocks. */
1415
class EventBlocks : public IBlockSection
1516
{
1617
public:
1718
enum Inputs
1819
{
19-
BROADCAST_INPUT
20+
BROADCAST_INPUT,
21+
VALUE
2022
};
2123

2224
enum Fields
2325
{
2426
BROADCAST_OPTION,
2527
BACKDROP,
28+
WHENGREATERTHANMENU,
2629
KEY_OPTION
2730
};
2831

32+
enum FieldValues
33+
{
34+
Loudness,
35+
Timer
36+
};
37+
2938
std::string name() const override;
3039

3140
void registerBlocks(IEngine *engine) override;
@@ -37,6 +46,8 @@ class EventBlocks : public IBlockSection
3746
static void compileBroadcastAndWait(Compiler *compiler);
3847
static void compileWhenBroadcastReceived(Compiler *compiler);
3948
static void compileWhenBackdropSwitchesTo(Compiler *compiler);
49+
static void compileWhenGreaterThanPredicate(Compiler *compiler);
50+
static void compileWhenGreaterThan(Compiler *compiler);
4051
static void compileWhenKeyPressed(Compiler *compiler);
4152

4253
static unsigned int broadcast(VirtualMachine *vm);
@@ -45,6 +56,11 @@ class EventBlocks : public IBlockSection
4556
static unsigned int broadcastByIndexAndWait(VirtualMachine *vm);
4657
static unsigned int checkBroadcast(VirtualMachine *vm);
4758
static unsigned int checkBroadcastByIndex(VirtualMachine *vm);
59+
60+
static unsigned int whenLoudnessGreaterThanPredicate(VirtualMachine *vm);
61+
static unsigned int whenTimerGreaterThanPredicate(VirtualMachine *vm);
62+
63+
static IAudioInput *audioInput;
4864
};
4965

5066
} // namespace libscratchcpp

src/engine/internal/engine.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@
3434
using namespace libscratchcpp;
3535

3636
const std::unordered_map<Engine::HatType, bool> Engine::m_hatRestartExistingThreads = {
37-
{ HatType::GreenFlag, true }, { HatType::BroadcastReceived, true }, { HatType::BackdropChanged, true },
38-
{ HatType::CloneInit, false }, { HatType::KeyPressed, false }, { HatType::TargetClicked, true }
37+
{ HatType::GreenFlag, true }, { HatType::BroadcastReceived, true }, { HatType::BackdropChanged, true }, { HatType::CloneInit, false },
38+
{ HatType::KeyPressed, false }, { HatType::TargetClicked, true }, { HatType::WhenGreaterThan, false }
3939
};
4040

4141
const std::unordered_map<Engine::HatType, bool> Engine::m_hatEdgeActivated = {
42-
{ HatType::GreenFlag, false }, { HatType::BroadcastReceived, false }, { HatType::BackdropChanged, false },
43-
{ HatType::CloneInit, false }, { HatType::KeyPressed, false }, { HatType::TargetClicked, false }
42+
{ HatType::GreenFlag, false }, { HatType::BroadcastReceived, false }, { HatType::BackdropChanged, false }, { HatType::CloneInit, false },
43+
{ HatType::KeyPressed, false }, { HatType::TargetClicked, false }, { HatType::WhenGreaterThan, true }
4444
};
4545

4646
Engine::Engine() :
@@ -82,6 +82,8 @@ void Engine::clear()
8282
m_broadcastHats.clear();
8383
m_cloneInitHats.clear();
8484
m_whenKeyPressedHats.clear();
85+
m_whenTargetClickedHats.clear();
86+
m_whenGreaterThanHats.clear();
8587

8688
m_scriptHatFields.clear();
8789
m_edgeActivatedHatValues.clear();
@@ -1034,6 +1036,12 @@ void Engine::addTargetClickScript(std::shared_ptr<Block> hatBlock)
10341036
addHatToMap(m_whenTargetClickedHats, m_scripts[hatBlock].get());
10351037
}
10361038

1039+
void Engine::addWhenGreaterThanScript(std::shared_ptr<Block> hatBlock)
1040+
{
1041+
Script *script = m_scripts[hatBlock].get();
1042+
addHatToMap(m_whenGreaterThanHats, script);
1043+
}
1044+
10371045
const std::vector<std::shared_ptr<Target>> &Engine::targets() const
10381046
{
10391047
return m_targets;
@@ -1442,6 +1450,9 @@ const std::vector<Script *> &Engine::getHats(Target *target, HatType type)
14421450
case HatType::TargetClicked:
14431451
return m_whenTargetClickedHats[target];
14441452

1453+
case HatType::WhenGreaterThan:
1454+
return m_whenGreaterThanHats[target];
1455+
14451456
default: {
14461457
static const std::vector<Script *> empty = {};
14471458
return empty;

src/engine/internal/engine.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class Engine : public IEngine
125125
void addCloneInitScript(std::shared_ptr<Block> hatBlock) override;
126126
void addKeyPressScript(std::shared_ptr<Block> hatBlock, int fieldId) override;
127127
void addTargetClickScript(std::shared_ptr<Block> hatBlock) override;
128+
void addWhenGreaterThanScript(std::shared_ptr<Block> hatBlock) override;
128129

129130
const std::vector<std::shared_ptr<Target>> &targets() const override;
130131
void setTargets(const std::vector<std::shared_ptr<Target>> &newTargets) override;
@@ -171,14 +172,16 @@ class Engine : public IEngine
171172
BackdropChanged,
172173
CloneInit,
173174
KeyPressed,
174-
TargetClicked
175+
TargetClicked,
176+
WhenGreaterThan
175177
};
176178

177179
enum class HatField
178180
{
179181
BroadcastOption,
180182
Backdrop,
181-
KeyOption
183+
KeyOption,
184+
WhenGreaterThanMenu
182185
};
183186

184187
std::vector<std::shared_ptr<VirtualMachine>> stepThreads();
@@ -240,6 +243,7 @@ class Engine : public IEngine
240243
std::unordered_map<Target *, std::vector<Script *>> m_cloneInitHats;
241244
std::unordered_map<Target *, std::vector<Script *>> m_whenKeyPressedHats;
242245
std::unordered_map<Target *, std::vector<Script *>> m_whenTargetClickedHats;
246+
std::unordered_map<Target *, std::vector<Script *>> m_whenGreaterThanHats;
243247

244248
std::unordered_map<Script *, std::unordered_map<HatField, int>> m_scriptHatFields; // HatField, field ID from the block implementation
245249

0 commit comments

Comments
 (0)