Skip to content

Commit bf24e61

Browse files
authored
Merge pull request #400 from scratchcpp/rewrite_event_loop
Rewrite the event loop to behave exactly like Scratch
2 parents a24b9bd + c6954ec commit bf24e61

29 files changed

+890
-585
lines changed

include/scratchcpp/broadcast.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ class BroadcastPrivate;
1313
class LIBSCRATCHCPP_EXPORT Broadcast : public Entity
1414
{
1515
public:
16-
Broadcast(const std::string &id, const std::string &name);
16+
Broadcast(const std::string &id, const std::string &name, bool isBackdropBroadcast = false);
1717
Broadcast(const Broadcast &) = delete;
1818

1919
const std::string &name() const;
2020
void setName(const std::string &newName);
2121

22+
bool isBackdropBroadcast() const;
23+
2224
private:
2325
spimpl::unique_impl_ptr<BroadcastPrivate> impl;
2426
};

include/scratchcpp/iengine.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,14 @@ class LIBSCRATCHCPP_EXPORT IEngine
5656
/*! Starts a script with the given top level block as the given Target (a sprite or the stage). */
5757
virtual VirtualMachine *startScript(std::shared_ptr<Block> topLevelBlock, Target *) = 0;
5858

59-
/*! Starts the script of the broadcast with the given index. */
60-
virtual void broadcast(unsigned int index, VirtualMachine *sourceScript, bool wait = false) = 0;
59+
/*! Starts the scripts of the broadcast with the given index. */
60+
virtual void broadcast(unsigned int index) = 0;
6161

62-
/*! Starts the script of the given broadcast. */
63-
virtual void broadcastByPtr(Broadcast *broadcast, VirtualMachine *sourceScript, bool wait = false) = 0;
62+
/*! Starts the scripts of the given broadcast. */
63+
virtual void broadcastByPtr(Broadcast *broadcast) = 0;
64+
65+
/*! Starts the "when backdrop switches to" scripts for the given backdrop broadcast. */
66+
virtual void startBackdropScripts(Broadcast *broadcast) = 0;
6467

6568
/*! Stops the given script. */
6669
virtual void stopScript(VirtualMachine *vm) = 0;
@@ -174,10 +177,10 @@ class LIBSCRATCHCPP_EXPORT IEngine
174177
virtual void setSpriteFencingEnabled(bool enable) = 0;
175178

176179
/*! Returns true if there are any running script of the broadcast with the given index. */
177-
virtual bool broadcastRunning(unsigned int index, VirtualMachine *sourceScript) = 0;
180+
virtual bool broadcastRunning(unsigned int index) = 0;
178181

179182
/*! Returns true if there are any running script of the given broadcast. */
180-
virtual bool broadcastByPtrRunning(Broadcast *broadcast, VirtualMachine *sourceScript) = 0;
183+
virtual bool broadcastByPtrRunning(Broadcast *broadcast) = 0;
181184

182185
/*!
183186
* Call this from a block implementation to force a redraw (screen refresh).
@@ -242,14 +245,20 @@ class LIBSCRATCHCPP_EXPORT IEngine
242245
/*! Returns the index of the broadcast with the given ID. */
243246
virtual int findBroadcastById(const std::string &broadcastId) const = 0;
244247

248+
/*! Registers the "green flag" script. */
249+
virtual void addGreenFlagScript(std::shared_ptr<Block> hatBlock) = 0;
250+
245251
/*! Registers the broadcast script. */
246-
virtual void addBroadcastScript(std::shared_ptr<Block> whenReceivedBlock, Broadcast *broadcast) = 0;
252+
virtual void addBroadcastScript(std::shared_ptr<Block> whenReceivedBlock, int fieldId, Broadcast *broadcast) = 0;
253+
254+
/*! Registers the backdrop change script. */
255+
virtual void addBackdropChangeScript(std::shared_ptr<Block> hatBlock, int fieldId) = 0;
247256

248257
/* Registers the given "when I start as clone" script. */
249258
virtual void addCloneInitScript(std::shared_ptr<Block> hatBlock) = 0;
250259

251260
/* Registers the given "when key pressed" script. */
252-
virtual void addKeyPressScript(std::shared_ptr<Block> hatBlock, std::string keyName) = 0;
261+
virtual void addKeyPressScript(std::shared_ptr<Block> hatBlock, int fieldId) = 0;
253262

254263
/*! Returns the list of targets. */
255264
virtual const std::vector<std::shared_ptr<Target>> &targets() const = 0;

include/scratchcpp/script.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace libscratchcpp
1212
{
1313

1414
class Target;
15+
class Block;
1516
class IEngine;
1617
class Value;
1718
class VirtualMachine;
@@ -23,10 +24,11 @@ class ScriptPrivate;
2324
class LIBSCRATCHCPP_EXPORT Script
2425
{
2526
public:
26-
Script(Target *target, IEngine *engine);
27+
Script(Target *target, std::shared_ptr<Block> topBlock, IEngine *engine);
2728
Script(const Script &) = delete;
2829

2930
Target *target() const;
31+
std::shared_ptr<Block> topBlock() const;
3032

3133
unsigned int *bytecode() const;
3234
const std::vector<unsigned int> &bytecodeVector() const;

include/scratchcpp/virtualmachine.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
128128
void replaceReturnValue(const Value &v, unsigned int offset);
129129

130130
void run();
131+
void kill();
131132
void reset();
132133
void moveToLastCheckpoint();
133134

src/blocks/eventblocks.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ std::string EventBlocks::name() const
2121
void EventBlocks::registerBlocks(IEngine *engine)
2222
{
2323
// Blocks
24-
engine->addHatBlock(this, "event_whenflagclicked");
24+
engine->addCompileFunction(this, "event_whenflagclicked", &compileWhenFlagClicked);
2525
engine->addCompileFunction(this, "event_broadcast", &compileBroadcast);
2626
engine->addCompileFunction(this, "event_broadcastandwait", &compileBroadcastAndWait);
2727
engine->addCompileFunction(this, "event_whenbroadcastreceived", &compileWhenBroadcastReceived);
@@ -37,6 +37,11 @@ void EventBlocks::registerBlocks(IEngine *engine)
3737
engine->addField(this, "KEY_OPTION", KEY_OPTION);
3838
}
3939

40+
void EventBlocks::compileWhenFlagClicked(Compiler *compiler)
41+
{
42+
compiler->engine()->addGreenFlagScript(compiler->block());
43+
}
44+
4045
void EventBlocks::compileBroadcast(Compiler *compiler)
4146
{
4247
auto input = compiler->input(BROADCAST_INPUT);
@@ -72,60 +77,54 @@ void EventBlocks::compileWhenBroadcastReceived(Compiler *compiler)
7277
{
7378
auto broadcast = std::static_pointer_cast<Broadcast>(compiler->field(BROADCAST_OPTION)->valuePtr());
7479

75-
compiler->engine()->addBroadcastScript(compiler->block(), broadcast.get());
80+
compiler->engine()->addBroadcastScript(compiler->block(), BROADCAST_OPTION, broadcast.get());
7681
}
7782

7883
void EventBlocks::compileWhenBackdropSwitchesTo(Compiler *compiler)
7984
{
80-
if (Stage *stage = compiler->engine()->stage()) {
81-
std::string backdropName = compiler->field(BACKDROP)->value().toString();
82-
int index = stage->findCostume(backdropName);
83-
84-
if (index != -1)
85-
compiler->engine()->addBroadcastScript(compiler->block(), stage->costumeAt(index)->broadcast());
86-
}
85+
compiler->engine()->addBackdropChangeScript(compiler->block(), BACKDROP);
8786
}
8887

8988
void EventBlocks::compileWhenKeyPressed(Compiler *compiler)
9089
{
9190
// NOTE: Field values don't have to be registered because keys are referenced by their names
92-
compiler->engine()->addKeyPressScript(compiler->block(), compiler->field(KEY_OPTION)->value().toString());
91+
compiler->engine()->addKeyPressScript(compiler->block(), KEY_OPTION);
9392
}
9493

9594
unsigned int EventBlocks::broadcast(VirtualMachine *vm)
9695
{
97-
vm->engine()->broadcast(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString()), vm);
96+
vm->engine()->broadcast(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString()));
9897
return 1;
9998
}
10099

101100
unsigned int EventBlocks::broadcastByIndex(VirtualMachine *vm)
102101
{
103-
vm->engine()->broadcast(vm->getInput(0, 1)->toLong(), vm);
102+
vm->engine()->broadcast(vm->getInput(0, 1)->toLong());
104103
return 1;
105104
}
106105

107106
unsigned int EventBlocks::broadcastAndWait(VirtualMachine *vm)
108107
{
109-
vm->engine()->broadcast(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString()), vm, true);
108+
vm->engine()->broadcast(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString()));
110109
return 1;
111110
}
112111

113112
unsigned int EventBlocks::broadcastByIndexAndWait(VirtualMachine *vm)
114113
{
115-
vm->engine()->broadcast(vm->getInput(0, 1)->toLong(), vm, true);
114+
vm->engine()->broadcast(vm->getInput(0, 1)->toLong());
116115
return 1;
117116
}
118117

119118
unsigned int EventBlocks::checkBroadcast(VirtualMachine *vm)
120119
{
121-
if (vm->engine()->broadcastRunning(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString()), vm))
120+
if (vm->engine()->broadcastRunning(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString())))
122121
vm->stop(true, true, true);
123122
return 1;
124123
}
125124

126125
unsigned int EventBlocks::checkBroadcastByIndex(VirtualMachine *vm)
127126
{
128-
if (vm->engine()->broadcastRunning(vm->getInput(0, 1)->toLong(), vm))
127+
if (vm->engine()->broadcastRunning(vm->getInput(0, 1)->toLong()))
129128
vm->stop(true, true, true);
130129
return 1;
131130
}

src/blocks/eventblocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class EventBlocks : public IBlockSection
3030

3131
void registerBlocks(IEngine *engine) override;
3232

33+
static void compileWhenFlagClicked(Compiler *compiler);
3334
static void compileBroadcast(Compiler *compiler);
3435
static void compileBroadcastAndWait(Compiler *compiler);
3536
static void compileWhenBroadcastReceived(Compiler *compiler);

src/blocks/looksblocks.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ void LooksBlocks::compileSwitchBackdropToAndWait(Compiler *compiler)
388388
compiler->addFunctionCall(&switchBackdropToAndWait);
389389
}
390390

391+
compiler->addFunctionCall(&backdropNumber);
391392
compiler->addFunctionCall(&checkBackdropScripts);
392393
}
393394

@@ -750,7 +751,7 @@ void LooksBlocks::startBackdropScripts(VirtualMachine *vm, bool wait)
750751
{
751752
if (Stage *stage = vm->engine()->stage()) {
752753
if (stage->costumes().size() > 0)
753-
vm->engine()->broadcastByPtr(stage->currentCostume()->broadcast(), vm, wait);
754+
vm->engine()->startBackdropScripts(stage->currentCostume()->broadcast());
754755
}
755756
}
756757

@@ -894,11 +895,14 @@ unsigned int LooksBlocks::randomBackdropAndWait(VirtualMachine *vm)
894895
unsigned int LooksBlocks::checkBackdropScripts(VirtualMachine *vm)
895896
{
896897
if (Stage *stage = vm->engine()->stage()) {
897-
if ((stage->costumes().size() > 0) && vm->engine()->broadcastByPtrRunning(stage->currentCostume()->broadcast(), vm))
898+
long index = vm->getInput(0, 1)->toLong() - 1;
899+
assert(stage->costumes().size() == 0 || index >= 0);
900+
901+
if ((stage->costumes().size() > 0) && vm->engine()->broadcastByPtrRunning(stage->costumeAt(index)->broadcast()))
898902
vm->stop(true, true, true);
899903
}
900904

901-
return 0;
905+
return 1;
902906
}
903907

904908
unsigned int LooksBlocks::goToFront(VirtualMachine *vm)

0 commit comments

Comments
 (0)