33#include < scratchcpp/iengine.h>
44#include < scratchcpp/compiler.h>
55#include < scratchcpp/block.h>
6+ #include < scratchcpp/input.h>
67#include < scratchcpp/field.h>
78#include < scratchcpp/broadcast.h>
89#include < scratchcpp/executioncontext.h>
910#include < scratchcpp/thread.h>
1011#include < scratchcpp/compilerconstant.h>
1112#include < scratchcpp/promise.h>
1213#include < scratchcpp/stringptr.h>
14+ #include < scratchcpp/sprite.h>
15+ #include < scratchcpp/itimer.h>
1316#include < utf8.h>
1417
1518#include " eventblocks.h"
19+ #include " audio/audioinput.h"
20+ #include " audio/iaudioloudness.h"
1621
1722using namespace libscratchcpp ;
1823
@@ -33,6 +38,7 @@ Rgb EventBlocks::color() const
3338
3439void EventBlocks::registerBlocks (IEngine *engine)
3540{
41+ // Blocks
3642 engine->addCompileFunction (this , " event_whentouchingobject" , &compileWhenTouchingObject);
3743 engine->addCompileFunction (this , " event_whenflagclicked" , &compileWhenFlagClicked);
3844 engine->addCompileFunction (this , " event_whenthisspriteclicked" , &compileWhenThisSpriteClicked);
@@ -43,6 +49,10 @@ void EventBlocks::registerBlocks(IEngine *engine)
4349 engine->addCompileFunction (this , " event_broadcast" , &compileBroadcast);
4450 engine->addCompileFunction (this , " event_broadcastandwait" , &compileBroadcastAndWait);
4551 engine->addCompileFunction (this , " event_whenkeypressed" , &compileWhenKeyPressed);
52+
53+ // Hat predicates
54+ engine->addHatPredicateCompileFunction (this , " event_whentouchingobject" , &compileWhenTouchingObjectPredicate);
55+ engine->addHatPredicateCompileFunction (this , " event_whengreaterthan" , &compileWhenGreaterThanPredicate);
4656}
4757
4858CompilerValue *EventBlocks::compileWhenTouchingObject (Compiler *compiler)
@@ -51,6 +61,21 @@ CompilerValue *EventBlocks::compileWhenTouchingObject(Compiler *compiler)
5161 return nullptr ;
5262}
5363
64+ CompilerValue *EventBlocks::compileWhenTouchingObjectPredicate (Compiler *compiler)
65+ {
66+ Input *input = compiler->input (" TOUCHINGOBJECTMENU" );
67+ CompilerValue *name = nullptr ;
68+
69+ if (input->pointsToDropdownMenu ()) {
70+ std::string value = input->selectedMenuItem ();
71+
72+ name = compiler->addConstValue (value);
73+ } else
74+ name = compiler->addInput (input);
75+
76+ return compiler->addTargetFunctionCall (" event_whentouchingobject_predicate" , Compiler::StaticType::Bool, { Compiler::StaticType::String }, { name });
77+ }
78+
5479CompilerValue *EventBlocks::compileWhenFlagClicked (Compiler *compiler)
5580{
5681 compiler->engine ()->addGreenFlagScript (compiler->block ());
@@ -99,6 +124,27 @@ CompilerValue *EventBlocks::compileWhenGreaterThan(Compiler *compiler)
99124 return nullptr ;
100125}
101126
127+ CompilerValue *EventBlocks::compileWhenGreaterThanPredicate (Compiler *compiler)
128+ {
129+ Field *field = compiler->field (" WHENGREATERTHANMENU" );
130+ std::string predicate;
131+
132+ if (field) {
133+ const std::string option = field->value ().toString ();
134+
135+ if (option == " LOUDNESS" )
136+ predicate = " event_whengreaterthan_loudness_predicate" ;
137+ else if (option == " TIMER" )
138+ predicate = " event_whengreaterthan_timer_predicate" ;
139+ else
140+ return compiler->addConstValue (false );
141+ } else
142+ return compiler->addConstValue (false );
143+
144+ CompilerValue *value = compiler->addInput (" VALUE" );
145+ return compiler->addFunctionCallWithCtx (predicate, Compiler::StaticType::Bool, { Compiler::StaticType::Number }, { value });
146+ }
147+
102148CompilerValue *EventBlocks::compileBroadcast (Compiler *compiler)
103149{
104150 auto input = compiler->addInput (" BROADCAST_INPUT" );
@@ -127,6 +173,43 @@ CompilerValue *EventBlocks::compileWhenKeyPressed(Compiler *compiler)
127173 return nullptr ;
128174}
129175
176+ extern " C" bool event_whentouchingobject_predicate (Target *target, const StringPtr *name)
177+ {
178+ static const StringPtr MOUSE_STR = StringPtr (" _mouse_" );
179+ static const StringPtr EDGE_STR = StringPtr (" _edge_" );
180+
181+ IEngine *engine = target->engine ();
182+
183+ if (string_compare_case_sensitive (name, &MOUSE_STR) == 0 )
184+ return target->touchingPoint (engine->mouseX (), engine->mouseY ());
185+ else if (string_compare_case_sensitive (name, &EDGE_STR) == 0 )
186+ return target->touchingEdge ();
187+ else {
188+ // TODO: Use UTF-16 in engine
189+ const std::string u8name = utf8::utf16to8 (std::u16string (name->data ));
190+ Target *anotherTarget = engine->targetAt (engine->findTarget (u8name));
191+
192+ if (anotherTarget && !anotherTarget->isStage ())
193+ return target->touchingSprite (static_cast <Sprite *>(anotherTarget));
194+ else
195+ return false ;
196+ }
197+ }
198+
199+ extern " C" bool event_whengreaterthan_loudness_predicate (ExecutionContext *ctx, double value)
200+ {
201+ if (!EventBlocks::audioInput)
202+ EventBlocks::audioInput = AudioInput::instance ().get ();
203+
204+ auto audioLoudness = EventBlocks::audioInput->audioLoudness ();
205+ return (audioLoudness->getLoudness () > value);
206+ }
207+
208+ extern " C" bool event_whengreaterthan_timer_predicate (ExecutionContext *ctx, double value)
209+ {
210+ return ctx->engine ()->timer ()->value () > value;
211+ }
212+
130213extern " C" void event_broadcast (ExecutionContext *ctx, const StringPtr *name, bool wait)
131214{
132215 Thread *thread = ctx->thread ();
0 commit comments