diff --git a/include/scratchcpp/iengine.h b/include/scratchcpp/iengine.h index df32aa87..a9587e38 100644 --- a/include/scratchcpp/iengine.h +++ b/include/scratchcpp/iengine.h @@ -360,6 +360,12 @@ class LIBSCRATCHCPP_EXPORT IEngine /*! Sets the list of monitors. */ virtual void setMonitors(const std::vector> &newMonitors) = 0; + /*! Creates a monitor for the given variable if it's missing and returns it. */ + virtual Monitor *createVariableMonitor(std::shared_ptr var, const std::string &opcode, const std::string &varFieldName, int varFieldId, BlockComp compileFunction) = 0; + + /*! Creates a monitor for the given list if it's missing and returns it. */ + virtual Monitor *createListMonitor(std::shared_ptr list, const std::string &opcode, const std::string &listFieldName, int listFieldId, BlockComp compileFunction) = 0; + /*! Emits when a monitor is added. */ virtual sigslot::signal &monitorAdded() = 0; diff --git a/src/blocks/listblocks.cpp b/src/blocks/listblocks.cpp index cabe63cb..b88ab1f3 100644 --- a/src/blocks/listblocks.cpp +++ b/src/blocks/listblocks.cpp @@ -142,11 +142,15 @@ void ListBlocks::compileHideList(Compiler *compiler) compiler->addFunctionCall(&hideList); } -void ListBlocks::setListVisible(std::shared_ptr list, bool visible) +void ListBlocks::setListVisible(std::shared_ptr list, bool visible, IEngine *engine) { if (list) { - assert(list->monitor()); - list->monitor()->setVisible(visible); + Monitor *monitor = list->monitor(); + + if (!monitor) + monitor = engine->createListMonitor(list, "data_listcontents", "LIST", LIST, &compileListContents); + + monitor->setVisible(visible); } } @@ -154,7 +158,7 @@ unsigned int ListBlocks::showGlobalList(VirtualMachine *vm) { if (Stage *target = vm->engine()->stage()) { int index = target->findListById(vm->getInput(0, 1)->toString()); - setListVisible(target->listAt(index), true); + setListVisible(target->listAt(index), true, vm->engine()); } return 1; @@ -166,10 +170,10 @@ unsigned int ListBlocks::showList(VirtualMachine *vm) if (!target->isStage() && static_cast(target)->isClone()) { Sprite *sprite = static_cast(target)->cloneSprite(); // use clone root list int index = sprite->findListById(vm->getInput(0, 1)->toString()); - setListVisible(sprite->listAt(index), true); + setListVisible(sprite->listAt(index), true, vm->engine()); } else { int index = target->findListById(vm->getInput(0, 1)->toString()); - setListVisible(target->listAt(index), true); + setListVisible(target->listAt(index), true, vm->engine()); } } @@ -180,7 +184,7 @@ unsigned int ListBlocks::hideGlobalList(VirtualMachine *vm) { if (Stage *target = vm->engine()->stage()) { int index = target->findListById(vm->getInput(0, 1)->toString()); - setListVisible(target->listAt(index), false); + setListVisible(target->listAt(index), false, vm->engine()); } return 1; @@ -192,10 +196,10 @@ unsigned int ListBlocks::hideList(VirtualMachine *vm) if (!target->isStage() && static_cast(target)->isClone()) { Sprite *sprite = static_cast(target)->cloneSprite(); // use clone root list int index = sprite->findListById(vm->getInput(0, 1)->toString()); - setListVisible(sprite->listAt(index), false); + setListVisible(sprite->listAt(index), false, vm->engine()); } else { int index = target->findListById(vm->getInput(0, 1)->toString()); - setListVisible(target->listAt(index), false); + setListVisible(target->listAt(index), false, vm->engine()); } } diff --git a/src/blocks/listblocks.h b/src/blocks/listblocks.h index 1fdcbd12..8fcf7b7f 100644 --- a/src/blocks/listblocks.h +++ b/src/blocks/listblocks.h @@ -43,7 +43,7 @@ class ListBlocks : public IBlockSection static void compileShowList(Compiler *compiler); static void compileHideList(Compiler *compiler); - static void setListVisible(std::shared_ptr list, bool visible); + static void setListVisible(std::shared_ptr list, bool visible, IEngine *engine); static unsigned int showGlobalList(VirtualMachine *vm); static unsigned int showList(VirtualMachine *vm); diff --git a/src/blocks/variableblocks.cpp b/src/blocks/variableblocks.cpp index 7bc4b82f..88b296d2 100644 --- a/src/blocks/variableblocks.cpp +++ b/src/blocks/variableblocks.cpp @@ -88,11 +88,15 @@ void VariableBlocks::compileHideVariable(Compiler *compiler) compiler->addFunctionCall(&hideVariable); } -void VariableBlocks::setVarVisible(std::shared_ptr var, bool visible) +void VariableBlocks::setVarVisible(std::shared_ptr var, bool visible, IEngine *engine) { if (var) { - assert(var->monitor()); - var->monitor()->setVisible(visible); + Monitor *monitor = var->monitor(); + + if (!monitor) + monitor = engine->createVariableMonitor(var, "data_variable", "VARIABLE", VARIABLE, &compileVariable); + + monitor->setVisible(visible); } } @@ -100,7 +104,7 @@ unsigned int VariableBlocks::showGlobalVariable(VirtualMachine *vm) { if (Stage *target = vm->engine()->stage()) { int index = target->findVariableById(vm->getInput(0, 1)->toString()); - setVarVisible(target->variableAt(index), true); + setVarVisible(target->variableAt(index), true, vm->engine()); } return 1; @@ -112,10 +116,10 @@ unsigned int VariableBlocks::showVariable(VirtualMachine *vm) if (!target->isStage() && static_cast(target)->isClone()) { Sprite *sprite = static_cast(target)->cloneSprite(); // use clone root variable int index = sprite->findVariableById(vm->getInput(0, 1)->toString()); - setVarVisible(sprite->variableAt(index), true); + setVarVisible(sprite->variableAt(index), true, vm->engine()); } else { int index = target->findVariableById(vm->getInput(0, 1)->toString()); - setVarVisible(target->variableAt(index), true); + setVarVisible(target->variableAt(index), true, vm->engine()); } } @@ -126,7 +130,7 @@ unsigned int VariableBlocks::hideGlobalVariable(VirtualMachine *vm) { if (Stage *target = vm->engine()->stage()) { int index = target->findVariableById(vm->getInput(0, 1)->toString()); - setVarVisible(target->variableAt(index), false); + setVarVisible(target->variableAt(index), false, vm->engine()); } return 1; @@ -138,10 +142,10 @@ unsigned int VariableBlocks::hideVariable(VirtualMachine *vm) if (!target->isStage() && static_cast(target)->isClone()) { Sprite *sprite = static_cast(target)->cloneSprite(); // use clone root variable int index = sprite->findVariableById(vm->getInput(0, 1)->toString()); - setVarVisible(sprite->variableAt(index), false); + setVarVisible(sprite->variableAt(index), false, vm->engine()); } else { int index = target->findVariableById(vm->getInput(0, 1)->toString()); - setVarVisible(target->variableAt(index), false); + setVarVisible(target->variableAt(index), false, vm->engine()); } } diff --git a/src/blocks/variableblocks.h b/src/blocks/variableblocks.h index 1d19a5be..27ecf99b 100644 --- a/src/blocks/variableblocks.h +++ b/src/blocks/variableblocks.h @@ -34,7 +34,7 @@ class VariableBlocks : public IBlockSection static void compileShowVariable(Compiler *compiler); static void compileHideVariable(Compiler *compiler); - static void setVarVisible(std::shared_ptr var, bool visible); + static void setVarVisible(std::shared_ptr var, bool visible, IEngine *engine); static unsigned int showGlobalVariable(VirtualMachine *vm); static unsigned int showVariable(VirtualMachine *vm); diff --git a/src/engine/internal/engine.cpp b/src/engine/internal/engine.cpp index 92f61279..1447e000 100644 --- a/src/engine/internal/engine.cpp +++ b/src/engine/internal/engine.cpp @@ -29,8 +29,6 @@ #include "clock.h" #include "audio/iaudioengine.h" #include "blocks/standardblocks.h" -#include "blocks/variableblocks.h" -#include "blocks/listblocks.h" #include "scratch/monitor_p.h" using namespace libscratchcpp; @@ -314,56 +312,8 @@ void Engine::compile() // Compile monitor blocks to bytecode std::cout << "Compiling stage monitors..." << std::endl; - for (auto monitor : m_monitors) { - Target *target = monitor->sprite() ? dynamic_cast(monitor->sprite()) : stage(); - Compiler compiler(this, target); - auto block = monitor->block(); - auto section = blockSection(block->opcode()); - auto container = blockSectionContainer(block->opcode()); - - if (container) { - MonitorNameFunc nameFunc = container->resolveMonitorNameFunc(block->opcode()); - - if (nameFunc) - monitor->setName(nameFunc(block.get())); - - MonitorChangeFunc changeFunc = container->resolveMonitorChangeFunc(block->opcode()); - monitor->setValueChangeFunction(changeFunc); - } - - if (section) { - auto script = std::make_shared