@@ -658,43 +658,12 @@ bool RenderedTarget::touchingClones(const std::vector<libscratchcpp::Sprite *> &
658
658
659
659
bool RenderedTarget::touchingColor (const Value &color) const
660
660
{
661
- // https://github.com/scratchfoundation/scratch-render/blob/0a04c2fb165f5c20406ec34ab2ea5682ae45d6e0/src/RenderWebGL.js#L775-L841
662
- if (!m_engine)
663
- return false ;
664
-
665
- QRgb rgb = convertColor (color);
666
-
667
- std::vector<Target *> targets;
668
- m_engine->getVisibleTargets (targets);
669
-
670
- QRectF myRect = touchingBounds ();
671
- std::vector<IRenderedTarget *> candidates;
672
- QRectF bounds = candidatesBounds (myRect, targets, candidates);
673
-
674
- if (colorMatches (rgb, qRgb (255 , 255 , 255 ))) {
675
- // The color we're checking for is the background color which spans the entire stage
676
- bounds = myRect;
677
-
678
- if (bounds.isEmpty ())
679
- return false ;
680
- } else if (candidates.empty ()) {
681
- // If not checking for the background color, we can return early if there are no candidate drawables
682
- return false ;
683
- }
684
-
685
- // Loop through the points of the union
686
- for (int y = bounds.top (); y <= bounds.bottom (); y++) {
687
- for (int x = bounds.left (); x <= bounds.right (); x++) {
688
- if (this ->containsScratchPoint (x, y)) {
689
- QRgb pixelColor = sampleColor3b (x, y, candidates);
690
-
691
- if (colorMatches (rgb, pixelColor))
692
- return true ;
693
- }
694
- }
695
- }
661
+ return touchingColor (color, false , Value ());
662
+ }
696
663
697
- return false ;
664
+ bool RenderedTarget::touchingColor (const Value &color, const Value &mask) const
665
+ {
666
+ return touchingColor (color, true , mask);
698
667
}
699
668
700
669
void RenderedTarget::calculatePos ()
@@ -896,6 +865,70 @@ CpuTextureManager *RenderedTarget::textureManager() const
896
865
return m_textureManager.get ();
897
866
}
898
867
868
+ bool RenderedTarget::touchingColor (const libscratchcpp::Value &color, bool hasMask, const libscratchcpp::Value &mask) const
869
+ {
870
+ // https://github.com/scratchfoundation/scratch-render/blob/0a04c2fb165f5c20406ec34ab2ea5682ae45d6e0/src/RenderWebGL.js#L775-L841
871
+ if (!m_engine)
872
+ return false ;
873
+
874
+ QRgb rgb = convertColor (color);
875
+ QRgb mask3b;
876
+ double ghostValue = 0 ;
877
+
878
+ if (hasMask) {
879
+ // Ignore ghost effect when checking mask
880
+ auto it = m_graphicEffects.find (ShaderManager::Effect::Ghost);
881
+
882
+ if (it != m_graphicEffects.cend ()) {
883
+ ghostValue = it->second ;
884
+ m_graphicEffects.erase (ShaderManager::Effect::Ghost);
885
+ }
886
+
887
+ mask3b = convertColor (mask);
888
+ }
889
+
890
+ std::vector<Target *> targets;
891
+ m_engine->getVisibleTargets (targets);
892
+
893
+ QRectF myRect = touchingBounds ();
894
+ std::vector<IRenderedTarget *> candidates;
895
+ QRectF bounds = candidatesBounds (myRect, targets, candidates);
896
+
897
+ if (colorMatches (rgb, qRgb (255 , 255 , 255 ))) {
898
+ // The color we're checking for is the background color which spans the entire stage
899
+ bounds = myRect;
900
+
901
+ if (bounds.isEmpty ())
902
+ return false ;
903
+ } else if (candidates.empty ()) {
904
+ // If not checking for the background color, we can return early if there are no candidate drawables
905
+ return false ;
906
+ }
907
+
908
+ // Loop through the points of the union
909
+ for (int y = bounds.top (); y <= bounds.bottom (); y++) {
910
+ for (int x = bounds.left (); x <= bounds.right (); x++) {
911
+ if (hasMask ? maskMatches (colorAtScratchPoint (x, y), mask3b) : this ->containsScratchPoint (x, y)) {
912
+ QRgb pixelColor = sampleColor3b (x, y, candidates);
913
+
914
+ if (colorMatches (rgb, pixelColor)) {
915
+ // Restore ghost effect value
916
+ if (hasMask && ghostValue != 0 )
917
+ m_graphicEffects[ShaderManager::Effect::Ghost] = ghostValue;
918
+
919
+ return true ;
920
+ }
921
+ }
922
+ }
923
+ }
924
+
925
+ // Restore ghost effect value
926
+ if (hasMask && ghostValue != 0 )
927
+ m_graphicEffects[ShaderManager::Effect::Ghost] = ghostValue;
928
+
929
+ return false ;
930
+ }
931
+
899
932
QRectF RenderedTarget::touchingBounds () const
900
933
{
901
934
// https://github.com/scratchfoundation/scratch-render/blob/0a04c2fb165f5c20406ec34ab2ea5682ae45d6e0/src/RenderWebGL.js#L1330-L1350
@@ -1051,7 +1084,13 @@ QRgb RenderedTarget::convertColor(const libscratchcpp::Value &color)
1051
1084
bool RenderedTarget::colorMatches (QRgb a, QRgb b)
1052
1085
{
1053
1086
// https://github.com/scratchfoundation/scratch-render/blob/0a04c2fb165f5c20406ec34ab2ea5682ae45d6e0/src/RenderWebGL.js#L77-L81
1054
- return (qRed (a) & 0b11111000 ) == (qRed (b) & 0b11111000 ) && (qGreen (a) & 0b11111000 ) == (qGreen (b) & 0b11111000 ) && (qBlue (a) & 0b11110000 ) == (qBlue (b) & 0b11110000 );
1087
+ return qAlpha (a) > 0 && (qRed (a) & 0b11111000 ) == (qRed (b) & 0b11111000 ) && (qGreen (a) & 0b11111000 ) == (qGreen (b) & 0b11111000 ) && (qBlue (a) & 0b11110000 ) == (qBlue (b) & 0b11110000 );
1088
+ }
1089
+
1090
+ bool RenderedTarget::maskMatches (QRgb a, QRgb b)
1091
+ {
1092
+ // https://github.com/scratchfoundation/scratch-render/blob/0a04c2fb165f5c20406ec34ab2ea5682ae45d6e0/src/RenderWebGL.js#L59-L65
1093
+ return (qRed (a) & 0b11111000 ) == (qRed (b) & 0b11111000 ) && (qGreen (a) & 0b11111000 ) == (qGreen (b) & 0b11111000 ) && (qBlue (a) & 0b11111000 ) == (qBlue (b) & 0b11111000 );
1055
1094
}
1056
1095
1057
1096
QRgb RenderedTarget::sampleColor3b (double x, double y, const std::vector<IRenderedTarget *> &targets) const
0 commit comments