Skip to content

Commit 401ed3d

Browse files
committed
Check the pen layer in touchingColor()
1 parent 270ebd9 commit 401ed3d

File tree

3 files changed

+53
-8
lines changed

3 files changed

+53
-8
lines changed

src/renderedtarget.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "bitmapskin.h"
1616
#include "svgskin.h"
1717
#include "cputexturemanager.h"
18+
#include "penlayer.h"
1819

1920
using namespace scratchcpprender;
2021
using namespace libscratchcpp;
@@ -216,6 +217,7 @@ void RenderedTarget::setEngine(IEngine *newEngine)
216217
m_texture = Texture();
217218
m_oldTexture = Texture();
218219
m_cpuTexture = Texture();
220+
m_penLayer = PenLayer::getProjectPenLayer(m_engine);
219221
m_convexHullDirty = true;
220222
clearGraphicEffects();
221223
m_hullPoints.clear();
@@ -941,6 +943,10 @@ QRectF RenderedTarget::candidatesBounds(const QRectF &targetRect, const std::vec
941943
}
942944
}
943945

946+
// Check pen layer
947+
if (m_penLayer)
948+
united = united.united(rectIntersection(targetRect, m_penLayer->getBounds()));
949+
944950
return united;
945951
}
946952

@@ -980,14 +986,19 @@ QRectF RenderedTarget::candidateIntersection(const QRectF &targetRect, IRendered
980986
if (target) {
981987
// Calculate the intersection of the bounding rectangles
982988
Rect scratchRect = target->getFastBounds();
983-
// TODO: Use Rect::snapToInt()
984-
QRect rect(QPoint(scratchRect.left(), scratchRect.bottom()), QPoint(scratchRect.right(), scratchRect.top()));
985-
return targetRect.intersected(rect);
989+
return rectIntersection(targetRect, scratchRect);
986990
}
987991

988992
return QRectF();
989993
}
990994

995+
QRectF RenderedTarget::rectIntersection(const QRectF &targetRect, const Rect &candidateRect)
996+
{
997+
// TODO: Use Rect::snapToInt()
998+
QRect rect(QPoint(candidateRect.left(), candidateRect.bottom()), QPoint(candidateRect.right(), candidateRect.top()));
999+
return targetRect.intersected(rect);
1000+
}
1001+
9911002
void RenderedTarget::clampRect(Rect &rect, double left, double right, double bottom, double top)
9921003
{
9931004
// TODO: Use Rect::clamp()
@@ -1035,16 +1046,31 @@ bool RenderedTarget::colorMatches(QRgb a, QRgb b)
10351046
return (qRed(a) & 0b11111000) == (qRed(b) & 0b11111000) && (qGreen(a) & 0b11111000) == (qGreen(b) & 0b11111000) && (qBlue(a) & 0b11110000) == (qBlue(b) & 0b11110000);
10361047
}
10371048

1038-
QRgb RenderedTarget::sampleColor3b(const QPointF &point, const std::vector<IRenderedTarget *> &targets)
1049+
QRgb RenderedTarget::sampleColor3b(const QPointF &point, const std::vector<IRenderedTarget *> &targets) const
10391050
{
10401051
// https://github.com/scratchfoundation/scratch-render/blob/0a04c2fb165f5c20406ec34ab2ea5682ae45d6e0/src/RenderWebGL.js#L1966-L1990
10411052
double blendAlpha = 1;
10421053
QRgb blendColor;
10431054
int r = 0, g = 0, b = 0;
1055+
bool penLayerChecked = false;
10441056

1045-
for (int i = 0; blendAlpha != 0 && i < targets.size(); i++) {
1046-
Q_ASSERT(targets[i]);
1047-
blendColor = targets[i]->colorAtScratchPoint(point.x(), point.y());
1057+
for (int i = 0; blendAlpha != 0 && i <= targets.size(); i++) { // NOTE: <= instead of < to process the pen layer
1058+
Q_ASSERT(i == targets.size() || targets[i]);
1059+
1060+
if ((i == targets.size() || targets[i]->stageModel()) && !penLayerChecked) {
1061+
if (m_penLayer)
1062+
blendColor = m_penLayer->colorAtScratchPoint(point.x(), point.y());
1063+
else
1064+
blendColor = qRgba(0, 0, 0, 0);
1065+
1066+
penLayerChecked = true;
1067+
1068+
if (i < targets.size())
1069+
i--; // check stage on next iteration
1070+
} else if (i == targets.size())
1071+
break;
1072+
else
1073+
blendColor = targets[i]->colorAtScratchPoint(point.x(), point.y());
10481074

10491075
r += qRed(blendColor) * blendAlpha;
10501076
g += qGreen(blendColor) * blendAlpha;

src/renderedtarget.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace scratchcpprender
2020

2121
class Skin;
2222
class CpuTextureManager;
23+
class IPenLayer;
2324

2425
class RenderedTarget : public IRenderedTarget
2526
{
@@ -131,16 +132,18 @@ class RenderedTarget : public IRenderedTarget
131132
QRectF candidatesBounds(const QRectF &targetRect, const std::vector<libscratchcpp::Target *> &candidates, std::vector<IRenderedTarget *> &dst) const;
132133
QRectF candidatesBounds(const QRectF &targetRect, const std::vector<libscratchcpp::Sprite *> &candidates, std::vector<IRenderedTarget *> &dst) const;
133134
static QRectF candidateIntersection(const QRectF &targetRect, IRenderedTarget *target);
135+
static QRectF rectIntersection(const QRectF &targetRect, const libscratchcpp::Rect &candidateRect);
134136
static void clampRect(libscratchcpp::Rect &rect, double left, double right, double bottom, double top);
135137
static QRgb convertColor(const libscratchcpp::Value &color);
136138
static bool colorMatches(QRgb a, QRgb b);
137-
static QRgb sampleColor3b(const QPointF &point, const std::vector<IRenderedTarget *> &targets);
139+
QRgb sampleColor3b(const QPointF &point, const std::vector<IRenderedTarget *> &targets) const;
138140

139141
libscratchcpp::IEngine *m_engine = nullptr;
140142
libscratchcpp::Costume *m_costume = nullptr;
141143
StageModel *m_stageModel = nullptr;
142144
SpriteModel *m_spriteModel = nullptr;
143145
SceneMouseArea *m_mouseArea = nullptr;
146+
IPenLayer *m_penLayer = nullptr;
144147
bool m_costumesLoaded = false;
145148
std::unordered_map<libscratchcpp::Costume *, Skin *> m_skins;
146149
bool m_skinsInherited = false;

test/renderedtarget/renderedtarget_test.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
#include <stagemodel.h>
77
#include <spritemodel.h>
88
#include <scenemousearea.h>
9+
#include <penlayer.h>
910
#include <scratchcpp/stage.h>
1011
#include <scratchcpp/sprite.h>
1112
#include <scratchcpp/costume.h>
1213
#include <scratchcpp/rect.h>
1314
#include <scratchcpp/value.h>
1415
#include <enginemock.h>
1516
#include <renderedtargetmock.h>
17+
#include <penlayermock.h>
1618

1719
#include "../common.h"
1820

@@ -1023,6 +1025,9 @@ TEST_F(RenderedTargetTest, TouchingColor)
10231025
parent.setWidth(480);
10241026
parent.setHeight(360);
10251027

1028+
PenLayerMock penLayer;
1029+
PenLayer::addPenLayer(&engine, &penLayer);
1030+
10261031
RenderedTarget target(&parent);
10271032
target.setEngine(&engine);
10281033
target.setSpriteModel(&model);
@@ -1049,7 +1054,12 @@ TEST_F(RenderedTargetTest, TouchingColor)
10491054
target.updateCostume(costume.get());
10501055
target.beforeRedraw();
10511056

1057+
Rect penBounds(5, 1, 6, -5);
10521058
EXPECT_CALL(engine, targets()).WillRepeatedly(ReturnRef(targets));
1059+
EXPECT_CALL(stageTarget, stageModel()).WillRepeatedly(Return(&stageModel));
1060+
EXPECT_CALL(target1, stageModel()).WillRepeatedly(Return(nullptr));
1061+
EXPECT_CALL(target2, stageModel()).WillRepeatedly(Return(nullptr));
1062+
EXPECT_CALL(penLayer, getBounds()).WillRepeatedly(ReturnRef(penBounds));
10531063

10541064
static const Value color1 = 4286611711; // "purple"
10551065
static const Value color2 = 596083443; // close to color1 and transparent
@@ -1071,6 +1081,7 @@ TEST_F(RenderedTargetTest, TouchingColor)
10711081
EXPECT_CALL(target1, colorAtScratchPoint(2, -1)).WillOnce(Return(color3Int));
10721082
EXPECT_CALL(target2, colorAtScratchPoint(3, -1)).WillOnce(Return(color4.toInt()));
10731083
EXPECT_CALL(target1, colorAtScratchPoint(3, -1)).WillOnce(Return(color4.toInt()));
1084+
EXPECT_CALL(penLayer, colorAtScratchPoint(3, -1)).WillOnce(Return(color4.toInt()));
10741085
EXPECT_CALL(stageTarget, colorAtScratchPoint(3, -1)).WillOnce(Return(color4.toInt()));
10751086
ASSERT_FALSE(target.touchingColor(color1));
10761087

@@ -1134,6 +1145,7 @@ TEST_F(RenderedTargetTest, TouchingColor)
11341145
EXPECT_CALL(target2, getFastBounds()).WillOnce(Return(Rect(-5, -6, 2, -8)));
11351146
EXPECT_CALL(target2, colorAtScratchPoint).Times(0);
11361147
EXPECT_CALL(target1, colorAtScratchPoint).Times(0);
1148+
EXPECT_CALL(penLayer, colorAtScratchPoint).Times(0);
11371149
EXPECT_CALL(stageTarget, colorAtScratchPoint).Times(0);
11381150
ASSERT_FALSE(target.touchingColor(color3));
11391151

@@ -1145,6 +1157,7 @@ TEST_F(RenderedTargetTest, TouchingColor)
11451157
EXPECT_CALL(target2, getFastBounds()).WillOnce(Return(Rect(-5 - 300, -6.5 + 200, 1.8 - 300, -8 + 200)));
11461158
EXPECT_CALL(target2, colorAtScratchPoint).Times(0);
11471159
EXPECT_CALL(target1, colorAtScratchPoint).Times(0);
1160+
EXPECT_CALL(penLayer, colorAtScratchPoint).Times(0);
11481161
EXPECT_CALL(stageTarget, colorAtScratchPoint).Times(0);
11491162
ASSERT_FALSE(target.touchingColor(color1));
11501163

@@ -1156,6 +1169,7 @@ TEST_F(RenderedTargetTest, TouchingColor)
11561169
EXPECT_CALL(target2, getFastBounds()).WillOnce(Return(Rect(-5 + 300, -6.5 + 200, 1.8 + 300, -8 + 200)));
11571170
EXPECT_CALL(target2, colorAtScratchPoint).Times(0);
11581171
EXPECT_CALL(target1, colorAtScratchPoint).Times(0);
1172+
EXPECT_CALL(penLayer, colorAtScratchPoint).Times(0);
11591173
EXPECT_CALL(stageTarget, colorAtScratchPoint).Times(0);
11601174
ASSERT_FALSE(target.touchingColor(color1));
11611175

@@ -1167,6 +1181,7 @@ TEST_F(RenderedTargetTest, TouchingColor)
11671181
EXPECT_CALL(target2, getFastBounds()).WillOnce(Return(Rect(-5 + 300, -6.5 - 200, 1.8 + 300, -8 - 200)));
11681182
EXPECT_CALL(target2, colorAtScratchPoint).Times(0);
11691183
EXPECT_CALL(target1, colorAtScratchPoint).Times(0);
1184+
EXPECT_CALL(penLayer, colorAtScratchPoint).Times(0);
11701185
EXPECT_CALL(stageTarget, colorAtScratchPoint).Times(0);
11711186
ASSERT_FALSE(target.touchingColor(color1));
11721187

@@ -1178,6 +1193,7 @@ TEST_F(RenderedTargetTest, TouchingColor)
11781193
EXPECT_CALL(target2, getFastBounds()).WillOnce(Return(Rect(-5 - 300, -6.5 - 200, 1.8 - 300, -8 - 200)));
11791194
EXPECT_CALL(target2, colorAtScratchPoint).Times(0);
11801195
EXPECT_CALL(target1, colorAtScratchPoint).Times(0);
1196+
EXPECT_CALL(penLayer, colorAtScratchPoint).Times(0);
11811197
EXPECT_CALL(stageTarget, colorAtScratchPoint).Times(0);
11821198
ASSERT_FALSE(target.touchingColor(color1));
11831199

0 commit comments

Comments
 (0)