An extension is a group of Scratch blocks, for example motion blocks.
Creating an extension
To create a custom extension, subclass IExtension and override name() and description() functions to return the name and the description of the extension. Then override registerBlocks() where you'll register the compile functions for blocks.
It's recommended to use the libscratchcpp namespace like this in your extension class:
The main namespace of the library.
Definition asset.h:10
Adding blocks
See the Scratch Wiki for more information about blocks.
Scratch projects are compiled by the Compiler class. To add a block, you have to let the compiler know how to compile it. Start by defining a compile function. For example, the compile function for a hello world block would look like this:
public:
...
static void compileHelloWorld(
Compiler *compiler);
static unsigned int helloWorld(VirtualMachine *vm);
};
void MyExtension::compileHelloWorld(
Compiler *compiler) {
}
unsigned int MyExtension::helloWorld(VirtualMachine *vm) {
std::cout << "Hello, world!" << std::endl;
return 0;
}
The Compiler class provides API for compiling Scratch scripts.
Definition compiler.h:33
CompilerValue * addFunctionCall(const std::string &functionName, StaticType returnType=StaticType::Void, const ArgTypes &argTypes={}, const Args &args={})
Definition compiler.cpp:141
The IExtension class is an interface for extensions.
Definition iextension.h:18
- Note
- Make sure the functions are static.
Register the compile function using the addCompileFunction() method in link libscratchcpp::IExtension::registerBlocks() registerBlocks() :
MyExtension::registerBlocks(
IEngine *engine) {
engine->
addCompileFunction(
this,
"myextension_helloworld", &MyExtension::compileHelloWorld);
}
The IEngine interface provides an API for running Scratch projects.
Definition iengine.h:41
virtual void addCompileFunction(IExtension *extension, const std::string &opcode, BlockComp f)=0
Where myextension_helloworld is the opcode of the hello world block.
Adding inputs
To add inputs, create an Inputs enumeration in your extension:
class MyExtension : public IExtension {
enum Inputs {
TEXT
};
...
};
Then add inputs in link libscratchcpp::IExtension::registerBlocks() registerBlocks() :
MyExtension::registerBlocks(
IEngine *engine) {
...
engine->addInput(this, "TEXT", TEXT);
}
The compiler will assign the input name with the TEXT ID. In this case, the ID is 0 because it's the first member of the enumeration.
To add the input to the compiled code, call the addInput() function:
void MyExtension::compileHelloWorld(
Compiler *compiler) {
}
CompilerValue * addInput(const std::string &name)
Definition compiler.cpp:240
The value of the input can be read during runtime using the getInput() function:
unsigned int MyExtension::helloWorld(VirtualMachine *vm) {
std::cout << "Hello, " << vm->getInput(0, 1)->toString() << "!" << std::endl;
return 1;
}
- Note
- The order of the inputs is the same as in the compile function. Do not use the
Inputs enumeration in runtime functions.
The first argument is the index of the input and the second argument is the amount of inputs.
- Note
- Make sure to return the amount of inputs in the
helloWorld function.
Adding fields
Fields are drop-down menus into which one cannot drop a reporter. Fields have a predefined set of values.
...
enum Fields {
ANIMAL
};
enum FieldValues {
Cat,
Dog
};
...
};
MyExtension::registerBlocks(
IEngine *engine) {
...
engine->addField(this, "ANIMAL", ANIMAL);
engine->addFieldValue(this, "Cat", Cat);
engine->addFieldValue(this, "Dog", Dog);
}
Because fields are handled at compile time, you can read them from the compile function:
void MyExtension::compileHelloWorld(
Compiler *compiler) {
int id = compiler->
field(ANIMAL)->specialValueId();
switch(id) {
case Cat:
break;
case Dog:
break;
default:
break;
}
}
unsigned int MyExtension::helloCat(VirtualMachine *vm) {
std::cout << "Hello, cat!" << std::endl;
return 0;
}
unsigned int MyExtension::helloDog(VirtualMachine *vm) {
std::cout << "Hello, dog!" << std::endl;
return 0;
}
Field * field(const std::string &name) const
Definition compiler.cpp:731
- Note
- Don't confuse specialValueId() with valueId() because valueId() stores the ID of the block, variable, list or broadcast selected in the dropdown list.
To get a pointer to the block, variable, list or broadcast selected in the dropdown list, use valuePtr() .
Registering the extension
Register the extension before loading a project, using the ScratchConfiguration class:
static void registerExtension(std::shared_ptr< IExtension > extension)
Definition scratchconfiguration.cpp:12