Skip to content
3 changes: 3 additions & 0 deletions include/scratchcpp/costume.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace libscratchcpp
{

class Broadcast;
class CostumePrivate;

/*! \brief The Costume class represents a Scratch costume. */
Expand All @@ -27,6 +28,8 @@ class LIBSCRATCHCPP_EXPORT Costume : public Asset
int rotationCenterY() const;
void setRotationCenterY(int newRotationCenterY);

Broadcast *broadcast();

private:
spimpl::unique_impl_ptr<CostumePrivate> impl;
};
Expand Down
8 changes: 7 additions & 1 deletion include/scratchcpp/iengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class LIBSCRATCHCPP_EXPORT IEngine
/*! Starts the script of the broadcast with the given index. */
virtual void broadcast(unsigned int index, VirtualMachine *sourceScript, bool wait = false) = 0;

/*! Starts the script of the given broadcast. */
virtual void broadcastByPtr(Broadcast *broadcast, VirtualMachine *sourceScript, bool wait = false) = 0;

/*! Stops the given script. */
virtual void stopScript(VirtualMachine *vm) = 0;

Expand Down Expand Up @@ -122,6 +125,9 @@ class LIBSCRATCHCPP_EXPORT IEngine
/*! Returns true if there are any running script of the broadcast with the given index. */
virtual bool broadcastRunning(unsigned int index, VirtualMachine *sourceScript) = 0;

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

/*!
* Call this from a block implementation to force a "screen refresh".
* \note This has no effect in "run without screen refresh" custom blocks.
Expand Down Expand Up @@ -199,7 +205,7 @@ class LIBSCRATCHCPP_EXPORT IEngine
virtual int findBroadcastById(const std::string &broadcastId) const = 0;

/*! Registers the broadcast script. */
virtual void addBroadcastScript(std::shared_ptr<Block> whenReceivedBlock, std::shared_ptr<Broadcast> broadcast) = 0;
virtual void addBroadcastScript(std::shared_ptr<Block> whenReceivedBlock, Broadcast *broadcast) = 0;

/* Registers the given "when I start as clone" script. */
virtual void addCloneInitScript(std::shared_ptr<Block> hatBlock) = 0;
Expand Down
17 changes: 16 additions & 1 deletion src/blocks/eventblocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <scratchcpp/input.h>
#include <scratchcpp/inputvalue.h>
#include <scratchcpp/field.h>
#include <scratchcpp/stage.h>
#include <scratchcpp/costume.h>

#include "eventblocks.h"

Expand All @@ -23,12 +25,14 @@ void EventBlocks::registerBlocks(IEngine *engine)
engine->addCompileFunction(this, "event_broadcast", &compileBroadcast);
engine->addCompileFunction(this, "event_broadcastandwait", &compileBroadcastAndWait);
engine->addCompileFunction(this, "event_whenbroadcastreceived", &compileWhenBroadcastReceived);
engine->addCompileFunction(this, "event_whenbackdropswitchesto", &compileWhenBackdropSwitchesTo);

// Inputs
engine->addInput(this, "BROADCAST_INPUT", BROADCAST_INPUT);

// Fields
engine->addField(this, "BROADCAST_OPTION", BROADCAST_OPTION);
engine->addField(this, "BACKDROP", BACKDROP);
}

void EventBlocks::compileBroadcast(Compiler *compiler)
Expand Down Expand Up @@ -66,7 +70,18 @@ void EventBlocks::compileWhenBroadcastReceived(Compiler *compiler)
{
auto broadcast = std::static_pointer_cast<Broadcast>(compiler->field(BROADCAST_OPTION)->valuePtr());

compiler->engine()->addBroadcastScript(compiler->block(), broadcast);
compiler->engine()->addBroadcastScript(compiler->block(), broadcast.get());
}

void EventBlocks::compileWhenBackdropSwitchesTo(Compiler *compiler)
{
if (Stage *stage = compiler->engine()->stage()) {
std::string backdropName = compiler->field(BACKDROP)->value().toString();
int index = stage->findCostume(backdropName);

if (index != -1)
compiler->engine()->addBroadcastScript(compiler->block(), stage->costumeAt(index)->broadcast());
}
}

unsigned int EventBlocks::broadcast(VirtualMachine *vm)
Expand Down
4 changes: 3 additions & 1 deletion src/blocks/eventblocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class EventBlocks : public IBlockSection

enum Fields
{
BROADCAST_OPTION
BROADCAST_OPTION,
BACKDROP
};

std::string name() const override;
Expand All @@ -31,6 +32,7 @@ class EventBlocks : public IBlockSection
static void compileBroadcast(Compiler *compiler);
static void compileBroadcastAndWait(Compiler *compiler);
static void compileWhenBroadcastReceived(Compiler *compiler);
static void compileWhenBackdropSwitchesTo(Compiler *compiler);

static unsigned int broadcast(VirtualMachine *vm);
static unsigned int broadcastByIndex(VirtualMachine *vm);
Expand Down
164 changes: 147 additions & 17 deletions src/blocks/looksblocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void LooksBlocks::registerBlocks(IEngine *engine)
engine->addCompileFunction(this, "looks_switchcostumeto", &compileSwitchCostumeTo);
engine->addCompileFunction(this, "looks_nextcostume", &compileNextCostume);
engine->addCompileFunction(this, "looks_switchbackdropto", &compileSwitchBackdropTo);
engine->addCompileFunction(this, "looks_switchbackdroptoandwait", &compileSwitchBackdropToAndWait);
engine->addCompileFunction(this, "looks_nextbackdrop", &compileNextBackdrop);
engine->addCompileFunction(this, "looks_costumenumbername", &compileCostumeNumberName);
engine->addCompileFunction(this, "looks_backdropnumbername", &compileBackdropNumberName);
Expand Down Expand Up @@ -157,6 +158,47 @@ void LooksBlocks::compileSwitchBackdropTo(Compiler *compiler)
}
}

void LooksBlocks::compileSwitchBackdropToAndWait(Compiler *compiler)
{
Stage *stage = compiler->engine()->stage();

if (!stage)
return;

Input *input = compiler->input(BACKDROP);

if (input->type() != Input::Type::ObscuredShadow) {
assert(input->pointsToDropdownMenu());
std::string value = input->selectedMenuItem();
int index = stage->findCostume(value);

if (index == -1) {
if (value == "next backdrop")
compiler->addFunctionCall(&nextBackdropAndWait);
else if (value == "previous backdrop")
compiler->addFunctionCall(&previousBackdropAndWait);
else if (value == "random backdrop")
compiler->addFunctionCall(&randomBackdropAndWait);
else {
Value v(value);

if (v.type() == Value::Type::Integer) {
compiler->addConstValue(v.toLong() - 1);
compiler->addFunctionCall(&switchBackdropToByIndexAndWait);
}
}
} else {
compiler->addConstValue(index);
compiler->addFunctionCall(&switchBackdropToByIndexAndWait);
}
} else {
compiler->addInput(input);
compiler->addFunctionCall(&switchBackdropToAndWait);
}

compiler->addFunctionCall(&checkBackdropScripts);
}

void LooksBlocks::compileNextBackdrop(Compiler *compiler)
{
compiler->addFunctionCall(&nextBackdrop);
Expand Down Expand Up @@ -308,59 +350,59 @@ unsigned int LooksBlocks::previousCostume(VirtualMachine *vm)
return 0;
}

unsigned int LooksBlocks::switchBackdropToByIndex(VirtualMachine *vm)
void LooksBlocks::startBackdropScripts(VirtualMachine *vm, bool wait)
{
if (Stage *stage = vm->engine()->stage()) {
if (stage->costumes().size() > 0)
vm->engine()->broadcastByPtr(stage->costumeAt(stage->currentCostume() - 1)->broadcast(), vm, wait);
}
}

void LooksBlocks::switchBackdropToByIndexImpl(VirtualMachine *vm)
{
if (Stage *stage = vm->engine()->stage())
setCostumeByIndex(stage, vm->getInput(0, 1)->toLong());

return 1;
}

unsigned int LooksBlocks::switchBackdropTo(VirtualMachine *vm)
void LooksBlocks::switchBackdropToImpl(VirtualMachine *vm)
{
Stage *stage = vm->engine()->stage();

if (!stage)
return 1;
return;

const Value *name = vm->getInput(0, 1);
std::string nameStr = name->toString();
int index = stage->findCostume(nameStr);

if (index == -1) {
if (nameStr == "next backdrop")
nextBackdrop(vm);
nextBackdropImpl(vm);
else if (nameStr == "previous backdrop")
previousBackdrop(vm);
previousBackdropImpl(vm);
else if (nameStr == "random backdrop") {
randomBackdrop(vm);
randomBackdropImpl(vm);
} else {
if (name->type() == Value::Type::Integer)
setCostumeByIndex(stage, name->toLong() - 1);
}
} else
setCostumeByIndex(stage, index);

return 1;
}

unsigned int LooksBlocks::nextBackdrop(VirtualMachine *vm)
void LooksBlocks::nextBackdropImpl(VirtualMachine *vm)
{
if (Stage *stage = vm->engine()->stage())
setCostumeByIndex(stage, stage->currentCostume());

return 0;
}

unsigned int LooksBlocks::previousBackdrop(VirtualMachine *vm)
void LooksBlocks::previousBackdropImpl(VirtualMachine *vm)
{
if (Stage *stage = vm->engine()->stage())
setCostumeByIndex(stage, stage->currentCostume() - 2);

return 0;
}

unsigned int LooksBlocks::randomBackdrop(VirtualMachine *vm)
void LooksBlocks::randomBackdropImpl(VirtualMachine *vm)
{
if (!rng)
rng = RandomGenerator::instance().get();
Expand All @@ -371,6 +413,94 @@ unsigned int LooksBlocks::randomBackdrop(VirtualMachine *vm)
if (count > 0)
stage->setCurrentCostume(rng->randint(1, count));
}
}

unsigned int LooksBlocks::switchBackdropToByIndex(VirtualMachine *vm)
{
switchBackdropToByIndexImpl(vm);
startBackdropScripts(vm, false);

return 1;
}

unsigned int LooksBlocks::switchBackdropTo(VirtualMachine *vm)
{
switchBackdropToImpl(vm);
startBackdropScripts(vm, false);

return 1;
}

unsigned int LooksBlocks::switchBackdropToByIndexAndWait(VirtualMachine *vm)
{
switchBackdropToByIndexImpl(vm);
startBackdropScripts(vm, true);

return 1;
}

unsigned int LooksBlocks::switchBackdropToAndWait(VirtualMachine *vm)
{
switchBackdropToImpl(vm);
startBackdropScripts(vm, true);

return 1;
}

unsigned int LooksBlocks::nextBackdrop(VirtualMachine *vm)
{
nextBackdropImpl(vm);
startBackdropScripts(vm, false);

return 0;
}

unsigned int LooksBlocks::nextBackdropAndWait(VirtualMachine *vm)
{
nextBackdropImpl(vm);
startBackdropScripts(vm, true);

return 0;
}

unsigned int LooksBlocks::previousBackdrop(VirtualMachine *vm)
{
previousBackdropImpl(vm);
startBackdropScripts(vm, false);

return 0;
}

unsigned int LooksBlocks::previousBackdropAndWait(VirtualMachine *vm)
{
previousBackdropImpl(vm);
startBackdropScripts(vm, true);

return 0;
}

unsigned int LooksBlocks::randomBackdrop(VirtualMachine *vm)
{
randomBackdropImpl(vm);
startBackdropScripts(vm, false);

return 0;
}

unsigned int LooksBlocks::randomBackdropAndWait(VirtualMachine *vm)
{
randomBackdropImpl(vm);
startBackdropScripts(vm, true);

return 0;
}

unsigned int LooksBlocks::checkBackdropScripts(VirtualMachine *vm)
{
if (Stage *stage = vm->engine()->stage()) {
if ((stage->costumes().size() > 0) && vm->engine()->broadcastByPtrRunning(stage->costumeAt(stage->currentCostume() - 1)->broadcast(), vm))
vm->stop(true, true, true);
}

return 0;
}
Expand Down
16 changes: 16 additions & 0 deletions src/blocks/looksblocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ namespace libscratchcpp
{

class Target;
class Stage;
class Value;
class IRandomGenerator;

/*! \brief The LooksBlocks class contains the implementation of looks blocks. */
Expand Down Expand Up @@ -45,6 +47,7 @@ class LooksBlocks : public IBlockSection
static void compileSwitchCostumeTo(Compiler *compiler);
static void compileNextCostume(Compiler *compiler);
static void compileSwitchBackdropTo(Compiler *compiler);
static void compileSwitchBackdropToAndWait(Compiler *compiler);
static void compileNextBackdrop(Compiler *compiler);
static void compileCostumeNumberName(Compiler *compiler);
static void compileBackdropNumberName(Compiler *compiler);
Expand All @@ -61,11 +64,24 @@ class LooksBlocks : public IBlockSection
static unsigned int nextCostume(VirtualMachine *vm);
static unsigned int previousCostume(VirtualMachine *vm);

static void startBackdropScripts(VirtualMachine *vm, bool wait);
static void switchBackdropToByIndexImpl(VirtualMachine *vm);
static void switchBackdropToImpl(VirtualMachine *vm);
static void nextBackdropImpl(VirtualMachine *vm);
static void previousBackdropImpl(VirtualMachine *vm);
static void randomBackdropImpl(VirtualMachine *vm);

static unsigned int switchBackdropToByIndex(VirtualMachine *vm);
static unsigned int switchBackdropTo(VirtualMachine *vm);
static unsigned int switchBackdropToByIndexAndWait(VirtualMachine *vm);
static unsigned int switchBackdropToAndWait(VirtualMachine *vm);
static unsigned int nextBackdrop(VirtualMachine *vm);
static unsigned int nextBackdropAndWait(VirtualMachine *vm);
static unsigned int previousBackdrop(VirtualMachine *vm);
static unsigned int previousBackdropAndWait(VirtualMachine *vm);
static unsigned int randomBackdrop(VirtualMachine *vm);
static unsigned int randomBackdropAndWait(VirtualMachine *vm);
static unsigned int checkBackdropScripts(VirtualMachine *vm);

static unsigned int costumeNumber(VirtualMachine *vm);
static unsigned int costumeName(VirtualMachine *vm);
Expand Down
Loading