Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions src/blocks/looksblocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@

#include "looksblocks.h"
#include "../engine/internal/randomgenerator.h"
#include "../engine/internal/clock.h"

using namespace libscratchcpp;

IRandomGenerator *LooksBlocks::rng = nullptr;
IClock *LooksBlocks::clock = nullptr;

std::string LooksBlocks::name() const
{
Expand All @@ -25,6 +27,10 @@ std::string LooksBlocks::name() const
void LooksBlocks::registerBlocks(IEngine *engine)
{
// Blocks
engine->addCompileFunction(this, "looks_sayforsecs", &compileSayForSecs);
engine->addCompileFunction(this, "looks_say", &compileSay);
engine->addCompileFunction(this, "looks_thinkforsecs", &compileThinkForSecs);
engine->addCompileFunction(this, "looks_think", &compileThink);
engine->addCompileFunction(this, "looks_show", &compileShow);
engine->addCompileFunction(this, "looks_hide", &compileHide);
engine->addCompileFunction(this, "looks_changeeffectby", &compileChangeEffectBy);
Expand All @@ -49,6 +55,8 @@ void LooksBlocks::registerBlocks(IEngine *engine)
engine->addMonitorNameFunction(this, "looks_size", &sizeMonitorName);

// Inputs
engine->addInput(this, "MESSAGE", MESSAGE);
engine->addInput(this, "SECS", SECS);
engine->addInput(this, "CHANGE", CHANGE);
engine->addInput(this, "SIZE", SIZE);
engine->addInput(this, "COSTUME", COSTUME);
Expand Down Expand Up @@ -77,6 +85,34 @@ void LooksBlocks::registerBlocks(IEngine *engine)
engine->addFieldValue(this, "backward", Backward);
}

void LooksBlocks::compileSayForSecs(Compiler *compiler)
{
compiler->addInput(MESSAGE);
compiler->addInput(SECS);
compiler->addFunctionCall(&startSayForSecs);
compiler->addFunctionCall(&sayForSecs);
}

void LooksBlocks::compileSay(Compiler *compiler)
{
compiler->addInput(MESSAGE);
compiler->addFunctionCall(&say);
}

void LooksBlocks::compileThinkForSecs(Compiler *compiler)
{
compiler->addInput(MESSAGE);
compiler->addInput(SECS);
compiler->addFunctionCall(&startThinkForSecs);
compiler->addFunctionCall(&thinkForSecs);
}

void LooksBlocks::compileThink(Compiler *compiler)
{
compiler->addInput(MESSAGE);
compiler->addFunctionCall(&think);
}

void LooksBlocks::compileShow(Compiler *compiler)
{
compiler->addFunctionCall(&show);
Expand Down Expand Up @@ -515,6 +551,114 @@ const std::string &LooksBlocks::sizeMonitorName(Block *block)
return name;
}

void LooksBlocks::startWait(VirtualMachine *vm, double secs)
{
if (!clock)
clock = Clock::instance().get();

auto currentTime = clock->currentSteadyTime();
m_timeMap[vm] = { currentTime, secs * 1000 };
vm->engine()->requestRedraw();
}

bool LooksBlocks::wait(VirtualMachine *vm)
{
if (!clock)
clock = Clock::instance().get();

auto currentTime = clock->currentSteadyTime();
assert(m_timeMap.count(vm) == 1);

if (std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - m_timeMap[vm].first).count() >= m_timeMap[vm].second) {
m_timeMap.erase(vm);
vm->stop(true, true, false);
return true;
} else {
vm->stop(true, true, true);
return false;
}
}

void LooksBlocks::showBubble(VirtualMachine *vm, Target::BubbleType type, const std::string &text)
{
Target *target = vm->target();

if (target) {
target->setBubbleType(type);
target->setBubbleText(text);
m_waitingBubbles.erase(target);
}
}

void LooksBlocks::hideBubble(Target *target)
{
if (!target)
return;

target->setBubbleText("");
m_waitingBubbles.erase(target);
}

unsigned int LooksBlocks::startSayForSecs(VirtualMachine *vm)
{
Target *target = vm->target();

if (target) {
showBubble(vm, Target::BubbleType::Say, vm->getInput(0, 2)->toString());
m_waitingBubbles[target] = vm;
startWait(vm, vm->getInput(1, 2)->toDouble());
}

return 2;
}

unsigned int LooksBlocks::sayForSecs(VirtualMachine *vm)
{
if (wait(vm)) {
Target *target = vm->target();

if (target) {
auto it = m_waitingBubbles.find(target);

// Clear bubble if it hasn't been changed
if (it != m_waitingBubbles.cend() && it->second == vm)
hideBubble(vm->target());
}
}

return 0;
}

unsigned int LooksBlocks::say(VirtualMachine *vm)
{
showBubble(vm, Target::BubbleType::Say, vm->getInput(0, 1)->toString());
return 1;
}

unsigned int LooksBlocks::startThinkForSecs(VirtualMachine *vm)
{
Target *target = vm->target();

if (target) {
showBubble(vm, Target::BubbleType::Think, vm->getInput(0, 2)->toString());
m_waitingBubbles[target] = vm;
startWait(vm, vm->getInput(1, 2)->toDouble());
}

return 2;
}

unsigned int LooksBlocks::thinkForSecs(VirtualMachine *vm)
{
return sayForSecs(vm); // there isn't any difference
}

unsigned int LooksBlocks::think(VirtualMachine *vm)
{
showBubble(vm, Target::BubbleType::Think, vm->getInput(0, 1)->toString());
return 1;
}

unsigned int LooksBlocks::show(VirtualMachine *vm)
{
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());
Expand Down
28 changes: 27 additions & 1 deletion src/blocks/looksblocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,28 @@
#pragma once

#include <scratchcpp/iblocksection.h>
#include <scratchcpp/target.h>
#include <vector>
#include <unordered_map>
#include <chrono>

namespace libscratchcpp
{

class Target;
class Stage;
class Value;
class IGraphicsEffect;
class IRandomGenerator;
class IClock;

/*! \brief The LooksBlocks class contains the implementation of looks blocks. */
class LooksBlocks : public IBlockSection
{
public:
enum Inputs
{
MESSAGE,
SECS,
CHANGE,
SIZE,
COSTUME,
Expand Down Expand Up @@ -57,6 +62,10 @@ class LooksBlocks : public IBlockSection

void registerBlocks(IEngine *engine) override;

static void compileSayForSecs(Compiler *compiler);
static void compileSay(Compiler *compiler);
static void compileThinkForSecs(Compiler *compiler);
static void compileThink(Compiler *compiler);
static void compileShow(Compiler *compiler);
static void compileHide(Compiler *compiler);
static void compileChangeEffectBy(Compiler *compiler);
Expand All @@ -79,6 +88,19 @@ class LooksBlocks : public IBlockSection
static const std::string &backdropNumberNameMonitorName(Block *block);
static const std::string &sizeMonitorName(Block *block);

static void startWait(VirtualMachine *vm, double secs);
static bool wait(VirtualMachine *vm);
static void showBubble(VirtualMachine *vm, Target::BubbleType type, const std::string &text);
static void hideBubble(Target *target);

static unsigned int startSayForSecs(VirtualMachine *vm);
static unsigned int sayForSecs(VirtualMachine *vm);
static unsigned int say(VirtualMachine *vm);

static unsigned int startThinkForSecs(VirtualMachine *vm);
static unsigned int thinkForSecs(VirtualMachine *vm);
static unsigned int think(VirtualMachine *vm);

static unsigned int show(VirtualMachine *vm);
static unsigned int hide(VirtualMachine *vm);

Expand Down Expand Up @@ -141,6 +163,9 @@ class LooksBlocks : public IBlockSection
static unsigned int backdropNumber(VirtualMachine *vm);
static unsigned int backdropName(VirtualMachine *vm);

static inline std::unordered_map<VirtualMachine *, std::pair<std::chrono::steady_clock::time_point, int>> m_timeMap;
static inline std::unordered_map<Target *, VirtualMachine *> m_waitingBubbles;

static inline std::vector<IGraphicsEffect *> m_customGraphicsEffects;
static inline IGraphicsEffect *m_colorEffect = nullptr;
static inline IGraphicsEffect *m_fisheyeEffect = nullptr;
Expand All @@ -151,6 +176,7 @@ class LooksBlocks : public IBlockSection
static inline IGraphicsEffect *m_ghostEffect = nullptr;

static IRandomGenerator *rng;
static IClock *clock;
};

} // namespace libscratchcpp
Loading