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
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ qt_add_qml_module(scratchcpp-render
penlayerpainter.cpp
penlayerpainter.h
penattributes.h
blocks/penextension.cpp
blocks/penextension.h
blocks/penblocks.cpp
blocks/penblocks.h
)

list(APPEND QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
Expand Down
83 changes: 83 additions & 0 deletions src/blocks/penblocks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: LGPL-3.0-or-later

#include <scratchcpp/compiler.h>
#include <scratchcpp/sprite.h>

#include "penblocks.h"
#include "penlayer.h"
#include "spritemodel.h"

using namespace scratchcpprender;
using namespace libscratchcpp;

std::string PenBlocks::name() const
{
return "Pen";
}

void PenBlocks::registerBlocks(IEngine *engine)
{
// Blocks
engine->addCompileFunction(this, "pen_clear", &compileClear);
engine->addCompileFunction(this, "pen_penDown", &compilePenDown);
engine->addCompileFunction(this, "pen_penUp", &compilePenUp);
}

void PenBlocks::compileClear(Compiler *compiler)
{
compiler->addFunctionCall(&clear);
}

void PenBlocks::compilePenDown(Compiler *compiler)
{
compiler->addFunctionCall(&penDown);
}

void PenBlocks::compilePenUp(Compiler *compiler)
{
compiler->addFunctionCall(&penUp);
}

unsigned int PenBlocks::clear(VirtualMachine *vm)
{
IPenLayer *penLayer = PenLayer::getProjectPenLayer(vm->engine());

if (penLayer) {
penLayer->clear();
vm->engine()->requestRedraw();
}

return 0;
}

unsigned int PenBlocks::penDown(VirtualMachine *vm)
{
Target *target = vm->target();

if (!target || target->isStage())
return 0;

Sprite *sprite = static_cast<Sprite *>(target);
SpriteModel *model = static_cast<SpriteModel *>(sprite->getInterface());

if (model)
model->setPenDown(true);

return 0;
}

unsigned int PenBlocks::penUp(libscratchcpp::VirtualMachine *vm)
{
Target *target = vm->target();

if (!target || target->isStage())
return 0;

Sprite *sprite = static_cast<Sprite *>(target);
SpriteModel *model = static_cast<SpriteModel *>(sprite->getInterface());

if (model)
model->setPenDown(false);

return 0;
}
30 changes: 30 additions & 0 deletions src/blocks/penblocks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include <scratchcpp/iblocksection.h>

namespace scratchcpprender
{

class PenBlocks : public libscratchcpp::IBlockSection
{
public:
enum Inputs
{
};

std::string name() const override;

void registerBlocks(libscratchcpp::IEngine *engine) override;

static void compileClear(libscratchcpp::Compiler *compiler);
static void compilePenDown(libscratchcpp::Compiler *compiler);
static void compilePenUp(libscratchcpp::Compiler *compiler);

static unsigned int clear(libscratchcpp::VirtualMachine *vm);
static unsigned int penDown(libscratchcpp::VirtualMachine *vm);
static unsigned int penUp(libscratchcpp::VirtualMachine *vm);
};

} // namespace scratchcpprender
24 changes: 24 additions & 0 deletions src/blocks/penextension.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: LGPL-3.0-or-later

#include <scratchcpp/iengine.h>

#include "penextension.h"
#include "penblocks.h"

using namespace scratchcpprender;
using namespace libscratchcpp;

std::string PenExtension::name() const
{
return "pen";
}

std::string PenExtension::description() const
{
return "Pen extension";
}

void PenExtension::registerSections(IEngine *engine)
{
engine->registerSection(std::make_shared<PenBlocks>());
}
19 changes: 19 additions & 0 deletions src/blocks/penextension.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include <scratchcpp/iextension.h>

namespace scratchcpprender
{

class PenExtension : public libscratchcpp::IExtension
{
public:
std::string name() const override;
std::string description() const override;

void registerSections(libscratchcpp::IEngine *engine) override;
};

} // namespace scratchcpprender
7 changes: 6 additions & 1 deletion src/penlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void PenLayer::setEngine(libscratchcpp::IEngine *newEngine)

m_engine = newEngine;

if (m_engine) {
if (m_engine && QOpenGLContext::currentContext()) {
m_projectPenLayers[m_engine] = this;
m_fbo = std::make_unique<QOpenGLFramebufferObject>(m_engine->stageWidth(), m_engine->stageHeight(), m_fboFormat);
Q_ASSERT(m_fbo->isValid());
Expand Down Expand Up @@ -134,6 +134,11 @@ IPenLayer *PenLayer::getProjectPenLayer(libscratchcpp::IEngine *engine)
return nullptr;
}

void PenLayer::addPenLayer(libscratchcpp::IEngine *engine, IPenLayer *penLayer)
{
m_projectPenLayers[engine] = penLayer;
}

QNanoQuickItemPainter *PenLayer::createItemPainter() const
{
return new PenLayerPainter;
Expand Down
1 change: 1 addition & 0 deletions src/penlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class PenLayer : public IPenLayer
QOpenGLFramebufferObject *framebufferObject() const override;

static IPenLayer *getProjectPenLayer(libscratchcpp::IEngine *engine);
static void addPenLayer(libscratchcpp::IEngine *engine, IPenLayer *penLayer); // for tests

signals:
void engineChanged();
Expand Down
5 changes: 5 additions & 0 deletions src/projectloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <scratchcpp/iengine.h>
#include <scratchcpp/value.h>
#include <scratchcpp/monitor.h>
#include <scratchcpp/scratchconfiguration.h>
#include <QtConcurrent/QtConcurrent>
#include <QApplication>

Expand All @@ -11,6 +12,7 @@
#include "valuemonitormodel.h"
#include "listmonitormodel.h"
#include "renderedtarget.h"
#include "blocks/penextension.h"

using namespace scratchcpprender;
using namespace libscratchcpp;
Expand All @@ -31,6 +33,9 @@ ProjectLoader::ProjectLoader(QObject *parent) :
});

initTimer();

// Register pen blocks
ScratchConfiguration::registerExtension(std::make_shared<PenExtension>());
}

ProjectLoader::~ProjectLoader()
Expand Down
18 changes: 13 additions & 5 deletions src/spritemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <scratchcpp/costume.h>
#include <scratchcpp/rect.h>
#include <scratchcpp/iengine.h>

#include "spritemodel.h"
#include "renderedtarget.h"
Expand Down Expand Up @@ -65,8 +66,13 @@ void SpriteModel::onYChanged(double y)

void SpriteModel::onMoved(double oldX, double oldY, double newX, double newY)
{
if (m_penDown && m_penLayer)
if (m_penDown && m_penLayer) {
m_penLayer->drawLine(m_penAttributes, oldX, oldY, newX, newY);
libscratchcpp::IEngine *engine = m_sprite->engine();

if (engine)
engine->requestRedraw();
}
}

void SpriteModel::onSizeChanged(double size)
Expand Down Expand Up @@ -151,13 +157,15 @@ bool SpriteModel::penDown() const

void SpriteModel::setPenDown(bool newPenDown)
{
if (m_penDown == newPenDown)
return;

m_penDown = newPenDown;

if (m_penDown && m_penLayer && m_sprite)
if (m_penDown && m_penLayer && m_sprite) {
m_penLayer->drawPoint(m_penAttributes, m_sprite->x(), m_sprite->y());
libscratchcpp::IEngine *engine = m_sprite->engine();

if (engine)
engine->requestRedraw();
}
}

SpriteModel *SpriteModel::cloneRoot() const
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ add_subdirectory(skins)
add_subdirectory(penattributes)
add_subdirectory(penlayer)
add_subdirectory(penlayerpainter)
add_subdirectory(blocks)
35 changes: 35 additions & 0 deletions test/blocks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# pen_blocks_test
add_executable(
pen_blocks_test
pen_blocks_test.cpp
)

target_link_libraries(
pen_blocks_test
GTest::gtest_main
GTest::gmock_main
scratchcpp-render
scratchcpprender_mocks
${QT_LIBS}
)

add_test(pen_blocks_test)
gtest_discover_tests(pen_blocks_test)

# penextension_test
add_executable(
penextension_test
penextension_test.cpp
)

target_link_libraries(
penextension_test
GTest::gtest_main
GTest::gmock_main
scratchcpp-render
scratchcpprender_mocks
${QT_LIBS}
)

add_test(penextension_test)
gtest_discover_tests(penextension_test)
Loading