Skip to content

Commit d7e05e2

Browse files
authored
Merge pull request #433 from scratchcpp/complete_monitors
Complete the monitor API
2 parents 5138865 + 9bcec4c commit d7e05e2

31 files changed

+628
-2
lines changed

include/scratchcpp/global.h

+18
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#define LIBSCRATCHCPP_EXPORT DECL_IMPORT
1818
#endif
1919

20+
#include <string>
21+
2022
/*! \brief The main namespace of the library. */
2123
namespace libscratchcpp
2224
{
@@ -29,6 +31,8 @@ enum class ScratchVersion
2931

3032
class VirtualMachine;
3133
class Compiler;
34+
class Block;
35+
class Value;
3236

3337
/*!
3438
* \typedef BlockFunc
@@ -44,6 +48,20 @@ using BlockFunc = unsigned int (*)(VirtualMachine *vm);
4448
*/
4549
using BlockComp = void (*)(Compiler *);
4650

51+
/*!
52+
* \typedef MonitorNameFunc
53+
*
54+
* MonitorNameFunc is a function pointer for functions which are used to get monitor names.
55+
*/
56+
using MonitorNameFunc = const std::string &(*)(Block *);
57+
58+
/*!
59+
* \typedef MonitorChangeFunc
60+
*
61+
* MonitorChangeFunc is a function pointer for functions which are used to change monitor values.
62+
*/
63+
using MonitorChangeFunc = void (*)(Block *, const Value &newValue);
64+
4765
} // namespace libscratchcpp
4866

4967
#endif // LIBSCRATCHCPP_GLOBAL_H

include/scratchcpp/iengine.h

+12
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,18 @@ class LIBSCRATCHCPP_EXPORT IEngine
217217
*/
218218
virtual void addCompileFunction(IBlockSection *section, const std::string &opcode, BlockComp f) = 0;
219219

220+
/*!
221+
* Call this from IBlockSection#registerBlocks() to add a monitor name function to a block section.
222+
* \see <a href="blockSections.html">Block sections</a>
223+
*/
224+
virtual void addMonitorNameFunction(IBlockSection *section, const std::string &opcode, MonitorNameFunc f) = 0;
225+
226+
/*!
227+
* Call this from IBlockSection#registerBlocks() to add a monitor value change function to a block section.
228+
* \see <a href="blockSections.html">Block sections</a>
229+
*/
230+
virtual void addMonitorChangeFunction(IBlockSection *section, const std::string &opcode, MonitorChangeFunc f) = 0;
231+
220232
/*!
221233
* Call this from IBlockSection#registerBlocks() to add a hat block to a block section.
222234
* \see <a href="blockSections.html">Block sections</a>

include/scratchcpp/monitor.h

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class LIBSCRATCHCPP_EXPORT Monitor : public Entity
3737

3838
void setInterface(IMonitorHandler *iface);
3939

40+
const std::string &name() const;
41+
4042
Mode mode() const;
4143
void setMode(Mode mode);
4244

@@ -54,6 +56,9 @@ class LIBSCRATCHCPP_EXPORT Monitor : public Entity
5456

5557
void updateValue(const VirtualMachine *vm);
5658

59+
void setValueChangeFunction(MonitorChangeFunc f);
60+
void changeValue(const Value &newValue);
61+
5762
unsigned int width() const;
5863
void setWidth(unsigned int width);
5964

src/blocks/listblocks.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <scratchcpp/iengine.h>
44
#include <scratchcpp/compiler.h>
55
#include <scratchcpp/field.h>
6+
#include <scratchcpp/block.h>
7+
#include <scratchcpp/list.h>
68

79
#include "listblocks.h"
810

@@ -32,6 +34,9 @@ void ListBlocks::registerBlocks(IEngine *engine)
3234
engine->addCompileFunction(this, "data_lengthoflist", &compileLengthOfList);
3335
engine->addCompileFunction(this, "data_listcontainsitem", &compileListContainsItem);
3436

37+
// Monitor names
38+
engine->addMonitorNameFunction(this, "data_listcontents", &listContentsMonitorName);
39+
3540
// Inputs
3641
engine->addInput(this, "ITEM", ITEM);
3742
engine->addInput(this, "INDEX", INDEX);
@@ -101,3 +106,15 @@ void ListBlocks::compileListContainsItem(Compiler *compiler)
101106
compiler->addInput(ITEM);
102107
compiler->addInstruction(vm::OP_LIST_CONTAINS, { compiler->listIndex(compiler->field(LIST)->valuePtr()) });
103108
}
109+
110+
const std::string &ListBlocks::listContentsMonitorName(Block *block)
111+
{
112+
List *list = dynamic_cast<List *>(block->findFieldById(LIST)->valuePtr().get());
113+
114+
if (list)
115+
return list->name();
116+
else {
117+
static const std::string empty = "";
118+
return empty;
119+
}
120+
}

src/blocks/listblocks.h

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ class ListBlocks : public IBlockSection
4040
static void compileLengthOfList(Compiler *compiler);
4141
static void compileListContainsItem(Compiler *compiler);
4242

43+
static const std::string &listContentsMonitorName(Block *block);
44+
4345
private:
4446
static int validateIndex(size_t index, size_t listLength);
4547
};

src/blocks/looksblocks.cpp

+56
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <scratchcpp/input.h>
88
#include <scratchcpp/field.h>
99
#include <scratchcpp/costume.h>
10+
#include <scratchcpp/block.h>
1011
#include <scratchcpp/scratchconfiguration.h>
1112

1213
#include "looksblocks.h"
@@ -42,6 +43,11 @@ void LooksBlocks::registerBlocks(IEngine *engine)
4243
engine->addCompileFunction(this, "looks_costumenumbername", &compileCostumeNumberName);
4344
engine->addCompileFunction(this, "looks_backdropnumbername", &compileBackdropNumberName);
4445

46+
// Monitor names
47+
engine->addMonitorNameFunction(this, "looks_costumenumbername", &costumeNumberNameMonitorName);
48+
engine->addMonitorNameFunction(this, "looks_backdropnumbername", &backdropNumberNameMonitorName);
49+
engine->addMonitorNameFunction(this, "looks_size", &sizeMonitorName);
50+
4551
// Inputs
4652
engine->addInput(this, "CHANGE", CHANGE);
4753
engine->addInput(this, "SIZE", SIZE);
@@ -459,6 +465,56 @@ void LooksBlocks::compileBackdropNumberName(Compiler *compiler)
459465
}
460466
}
461467

468+
const std::string &LooksBlocks::costumeNumberNameMonitorName(Block *block)
469+
{
470+
int option = block->findFieldById(NUMBER_NAME)->specialValueId();
471+
472+
switch (option) {
473+
case Number: {
474+
static const std::string name = "costume number";
475+
return name;
476+
}
477+
478+
case Name: {
479+
static const std::string name = "costume name";
480+
return name;
481+
}
482+
483+
default: {
484+
static const std::string name = "";
485+
return name;
486+
}
487+
}
488+
}
489+
490+
const std::string &LooksBlocks::backdropNumberNameMonitorName(Block *block)
491+
{
492+
int option = block->findFieldById(NUMBER_NAME)->specialValueId();
493+
494+
switch (option) {
495+
case Number: {
496+
static const std::string name = "backdrop number";
497+
return name;
498+
}
499+
500+
case Name: {
501+
static const std::string name = "backdrop name";
502+
return name;
503+
}
504+
505+
default: {
506+
static const std::string name = "";
507+
return name;
508+
}
509+
}
510+
}
511+
512+
const std::string &LooksBlocks::sizeMonitorName(Block *block)
513+
{
514+
static const std::string name = "size";
515+
return name;
516+
}
517+
462518
unsigned int LooksBlocks::show(VirtualMachine *vm)
463519
{
464520
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());

src/blocks/looksblocks.h

+4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ class LooksBlocks : public IBlockSection
7575
static void compileCostumeNumberName(Compiler *compiler);
7676
static void compileBackdropNumberName(Compiler *compiler);
7777

78+
static const std::string &costumeNumberNameMonitorName(Block *block);
79+
static const std::string &backdropNumberNameMonitorName(Block *block);
80+
static const std::string &sizeMonitorName(Block *block);
81+
7882
static unsigned int show(VirtualMachine *vm);
7983
static unsigned int hide(VirtualMachine *vm);
8084

src/blocks/motionblocks.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ void MotionBlocks::registerBlocks(IEngine *engine)
4545
engine->addCompileFunction(this, "motion_yposition", &compileYPosition);
4646
engine->addCompileFunction(this, "motion_direction", &compileDirection);
4747

48+
// Monitor names
49+
engine->addMonitorNameFunction(this, "motion_xposition", &xPositionMonitorName);
50+
engine->addMonitorNameFunction(this, "motion_yposition", &yPositionMonitorName);
51+
engine->addMonitorNameFunction(this, "motion_direction", &directionMonitorName);
52+
4853
// Inputs
4954
engine->addInput(this, "STEPS", STEPS);
5055
engine->addInput(this, "DEGREES", DEGREES);
@@ -245,6 +250,24 @@ void MotionBlocks::compileDirection(Compiler *compiler)
245250
compiler->addFunctionCall(&direction);
246251
}
247252

253+
const std::string &MotionBlocks::xPositionMonitorName(Block *block)
254+
{
255+
static const std::string name = "x position";
256+
return name;
257+
}
258+
259+
const std::string &MotionBlocks::yPositionMonitorName(Block *block)
260+
{
261+
static const std::string name = "y position";
262+
return name;
263+
}
264+
265+
const std::string &MotionBlocks::directionMonitorName(Block *block)
266+
{
267+
static const std::string name = "direction";
268+
return name;
269+
}
270+
248271
unsigned int MotionBlocks::moveSteps(VirtualMachine *vm)
249272
{
250273
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());

src/blocks/motionblocks.h

+4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ class MotionBlocks : public IBlockSection
6767
static void compileYPosition(Compiler *compiler);
6868
static void compileDirection(Compiler *compiler);
6969

70+
static const std::string &xPositionMonitorName(Block *block);
71+
static const std::string &yPositionMonitorName(Block *block);
72+
static const std::string &directionMonitorName(Block *block);
73+
7074
static unsigned int moveSteps(VirtualMachine *vm);
7175
static unsigned int turnRight(VirtualMachine *vm);
7276
static unsigned int turnLeft(VirtualMachine *vm);

src/blocks/sensingblocks.cpp

+86
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <scratchcpp/stage.h>
1111
#include <scratchcpp/costume.h>
1212
#include <scratchcpp/variable.h>
13+
#include <scratchcpp/block.h>
1314
#include "sensingblocks.h"
1415

1516
#include "../engine/internal/clock.h"
@@ -38,6 +39,14 @@ void SensingBlocks::registerBlocks(IEngine *engine)
3839
engine->addCompileFunction(this, "sensing_current", &compileCurrent);
3940
engine->addCompileFunction(this, "sensing_dayssince2000", &compileDaysSince2000);
4041

42+
// Monitor names
43+
engine->addMonitorNameFunction(this, "sensing_mousedown", &mouseDownMonitorName);
44+
engine->addMonitorNameFunction(this, "sensing_mousex", &mouseXMonitorName);
45+
engine->addMonitorNameFunction(this, "sensing_mousey", &mouseYMonitorName);
46+
engine->addMonitorNameFunction(this, "sensing_timer", &timerMonitorName);
47+
engine->addMonitorNameFunction(this, "sensing_current", &currentMonitorName);
48+
engine->addMonitorNameFunction(this, "sensing_dayssince2000", &daysSince2000MonitorName);
49+
4150
// Inputs
4251
engine->addInput(this, "DISTANCETOMENU", DISTANCETOMENU);
4352
engine->addInput(this, "KEY_OPTION", KEY_OPTION);
@@ -310,6 +319,83 @@ void SensingBlocks::compileDaysSince2000(Compiler *compiler)
310319
compiler->addFunctionCall(&daysSince2000);
311320
}
312321

322+
const std::string &SensingBlocks::mouseDownMonitorName(Block *block)
323+
{
324+
static const std::string name = "mouse down?";
325+
return name;
326+
}
327+
328+
const std::string &SensingBlocks::mouseXMonitorName(Block *block)
329+
{
330+
static const std::string name = "mouse x";
331+
return name;
332+
}
333+
334+
const std::string &SensingBlocks::mouseYMonitorName(Block *block)
335+
{
336+
static const std::string name = "mouse y";
337+
return name;
338+
}
339+
340+
const std::string &SensingBlocks::timerMonitorName(Block *block)
341+
{
342+
static const std::string name = "timer";
343+
return name;
344+
}
345+
346+
const std::string &SensingBlocks::currentMonitorName(Block *block)
347+
{
348+
int id = block->findFieldById(CURRENTMENU)->specialValueId();
349+
350+
switch (id) {
351+
case YEAR: {
352+
static const std::string name = "year";
353+
return name;
354+
}
355+
356+
case MONTH: {
357+
static const std::string name = "month";
358+
return name;
359+
}
360+
361+
case DATE: {
362+
static const std::string name = "date";
363+
return name;
364+
}
365+
366+
case DAYOFWEEK: {
367+
static const std::string name = "day of week";
368+
return name;
369+
}
370+
371+
case HOUR: {
372+
static const std::string name = "hour";
373+
return name;
374+
}
375+
376+
case MINUTE: {
377+
static const std::string name = "minute";
378+
return name;
379+
}
380+
381+
case SECOND: {
382+
static const std::string name = "second";
383+
return name;
384+
}
385+
386+
default: {
387+
static const std::string name = "";
388+
return name;
389+
}
390+
}
391+
}
392+
393+
const std::string &SensingBlocks::daysSince2000MonitorName(Block *block)
394+
{
395+
static const std::string name = "days since 2000";
396+
return name;
397+
}
398+
313399
unsigned int SensingBlocks::keyPressed(VirtualMachine *vm)
314400
{
315401
vm->replaceReturnValue(vm->engine()->keyPressed(vm->getInput(0, 1)->toString()), 1);

src/blocks/sensingblocks.h

+7
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ class SensingBlocks : public IBlockSection
6464
static void compileCurrent(Compiler *compiler);
6565
static void compileDaysSince2000(Compiler *compiler);
6666

67+
static const std::string &mouseDownMonitorName(Block *block);
68+
static const std::string &mouseXMonitorName(Block *block);
69+
static const std::string &mouseYMonitorName(Block *block);
70+
static const std::string &timerMonitorName(Block *block);
71+
static const std::string &currentMonitorName(Block *block);
72+
static const std::string &daysSince2000MonitorName(Block *block);
73+
6774
static unsigned int keyPressed(VirtualMachine *vm);
6875
static unsigned int mouseDown(VirtualMachine *vm);
6976
static unsigned int mouseX(VirtualMachine *vm);

0 commit comments

Comments
 (0)