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
48 changes: 48 additions & 0 deletions src/dev/blocks/variableblocks.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
// SPDX-License-Identifier: Apache-2.0

#include <scratchcpp/iengine.h>
#include <scratchcpp/dev/compiler.h>
#include <scratchcpp/dev/compilerconstant.h>
#include <scratchcpp/input.h>
#include <scratchcpp/field.h>
#include <scratchcpp/variable.h>

#include "variableblocks.h"

using namespace libscratchcpp;
Expand All @@ -16,4 +23,45 @@ std::string VariableBlocks::description() const

void VariableBlocks::registerBlocks(IEngine *engine)
{
engine->addCompileFunction(this, "data_variable", &compileVariable);
engine->addCompileFunction(this, "data_setvariableto", &compileSetVariableTo);
engine->addCompileFunction(this, "data_changevariableby", &compileChangeVariableBy);
}

CompilerValue *VariableBlocks::compileVariable(Compiler *compiler)
{
Field *varField = compiler->field("VARIABLE");
Variable *var = static_cast<Variable *>(varField->valuePtr().get());
assert(var);

if (var)
return compiler->addVariableValue(var);
else
return compiler->addConstValue(Value());
}

CompilerValue *VariableBlocks::compileSetVariableTo(Compiler *compiler)
{
Field *varField = compiler->field("VARIABLE");
Variable *var = static_cast<Variable *>(varField->valuePtr().get());
assert(var);

if (var)
compiler->createVariableWrite(var, compiler->addInput("VALUE"));

return nullptr;
}

CompilerValue *VariableBlocks::compileChangeVariableBy(Compiler *compiler)
{
Field *varField = compiler->field("VARIABLE");
Variable *var = static_cast<Variable *>(varField->valuePtr().get());
assert(var);

if (var) {
CompilerValue *value = compiler->createAdd(compiler->addVariableValue(var), compiler->addInput("VALUE"));
compiler->createVariableWrite(var, value);
}

return nullptr;
}
5 changes: 5 additions & 0 deletions src/dev/blocks/variableblocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ class VariableBlocks : public IExtension
std::string description() const override;

void registerBlocks(IEngine *engine) override;

private:
static CompilerValue *compileVariable(Compiler *compiler);
static CompilerValue *compileSetVariableTo(Compiler *compiler);
static CompilerValue *compileChangeVariableBy(Compiler *compiler);
};

} // namespace libscratchcpp
98 changes: 97 additions & 1 deletion test/dev/blocks/variable_blocks_test.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,111 @@
#include <scratchcpp/project.h>
#include <scratchcpp/sprite.h>
#include <scratchcpp/variable.h>
#include <scratchcpp/list.h>
#include <scratchcpp/dev/compiler.h>
#include <scratchcpp/dev/test/scriptbuilder.h>
#include <enginemock.h>

#include "../common.h"
#include "dev/blocks/variableblocks.h"

using namespace libscratchcpp;
using namespace libscratchcpp::test;

class VariableBlocksTest : public testing::Test
{
public:
void SetUp() override { m_extension = std::make_unique<VariableBlocks>(); }
void SetUp() override
{
m_extension = std::make_unique<VariableBlocks>();
m_engine = m_project.engine().get();
m_extension->registerBlocks(m_engine);
}

std::unique_ptr<IExtension> m_extension;
Project m_project;
IEngine *m_engine = nullptr;
EngineMock m_engineMock;
};

TEST_F(VariableBlocksTest, Variable)
{
auto target = std::make_shared<Sprite>();
auto var1 = std::make_shared<Variable>("", "", 835.21);
target->addVariable(var1);
auto var2 = std::make_shared<Variable>("", "", "Hello world");
target->addVariable(var2);
ScriptBuilder builder(m_extension.get(), m_engine, target);

builder.addBlock("data_variable");
builder.addEntityField("VARIABLE", var1);
builder.captureBlockReturnValue();

builder.addBlock("data_variable");
builder.addEntityField("VARIABLE", var2);
builder.captureBlockReturnValue();

builder.build();
builder.run();

List *valueList = builder.capturedValues();
ValueData *values = valueList->data();
ASSERT_EQ(valueList->size(), 2);
ASSERT_EQ(Value(values[0]), 835.21);
ASSERT_EQ(Value(values[1]), "Hello world");
}

TEST_F(VariableBlocksTest, SetVariableTo)
{
auto target = std::make_shared<Sprite>();
auto var1 = std::make_shared<Variable>("", "", 835.21);
target->addVariable(var1);
auto var2 = std::make_shared<Variable>("", "", "Hello world");
target->addVariable(var2);
ScriptBuilder builder(m_extension.get(), m_engine, target);

builder.addBlock("data_setvariableto");
builder.addEntityField("VARIABLE", var1);
builder.addValueInput("VALUE", "test");

builder.addBlock("data_setvariableto");
builder.addEntityField("VARIABLE", var2);
builder.addValueInput("VALUE", 123);

builder.build();
builder.run();
ASSERT_EQ(var1->value(), "test");
ASSERT_EQ(var2->value(), 123);
}

TEST_F(VariableBlocksTest, ChangeVariableBy)
{
auto target = std::make_shared<Sprite>();
auto var1 = std::make_shared<Variable>("", "", 835.21);
target->addVariable(var1);
auto var2 = std::make_shared<Variable>("", "", "Hello world");
target->addVariable(var2);
ScriptBuilder builder(m_extension.get(), m_engine, target);

builder.addBlock("data_changevariableby");
builder.addEntityField("VARIABLE", var1);
builder.addValueInput("VALUE", "5.12");

builder.addBlock("data_changevariableby");
builder.addEntityField("VARIABLE", var2);
builder.addValueInput("VALUE", -2.5);

builder.build();

builder.run();
ASSERT_EQ(var1->value(), 840.33);
ASSERT_EQ(var2->value(), -2.5);

builder.run();
ASSERT_EQ(var1->value(), 845.45);
ASSERT_EQ(var2->value(), -5);

builder.run();
ASSERT_EQ(var1->value(), 850.57);
ASSERT_EQ(var2->value(), -7.5);
}
Loading