11// SPDX-License-Identifier: Apache-2.0
22
33#include < scratchcpp/ispritehandler.h>
4+ #include < scratchcpp/rect.h>
5+ #include < scratchcpp/costume.h>
6+ #include < cmath>
47
58#include " sprite_p.h"
69
710using namespace libscratchcpp ;
811
9- SpritePrivate::SpritePrivate ()
12+ static const double pi = std::acos(-1 ); // TODO: Use std::numbers::pi in C++20
13+
14+ SpritePrivate::SpritePrivate (Sprite *sprite) :
15+ sprite(sprite)
1016{
1117}
1218
@@ -28,3 +34,59 @@ void SpritePrivate::setCostumeData(const char *data)
2834 if (iface)
2935 iface->onCostumeChanged (data);
3036}
37+
38+ void SpritePrivate::getBoundingRect (Rect *out) const
39+ {
40+ assert (out);
41+ assert (sprite);
42+ // TODO: Make currentCostume() return the costume
43+ auto costume = sprite->costumeAt (sprite->currentCostume () - 1 );
44+
45+ if (!costume) {
46+ out->setLeft (0 );
47+ out->setTop (0 );
48+ out->setRight (0 );
49+ out->setBottom (0 );
50+ return ;
51+ }
52+
53+ double cosTheta = std::cos ((90 - direction) * pi / 180 );
54+ double sinTheta = std::sin ((90 - direction) * pi / 180 );
55+ double maxX = 0 , maxY = 0 , minX = 0 , minY = 0 ;
56+ bool firstPixel = true ;
57+ unsigned int width = costume->width ();
58+ unsigned int height = costume->height ();
59+ double rotationCenterX = width / 2.0 + costume->rotationCenterX ();
60+ double rotationCenterY = height / 2.0 + costume->rotationCenterY ();
61+ Rgb **bitmap = costume->bitmap ();
62+
63+ for (unsigned int y = 0 ; y < height; y++) {
64+ for (unsigned int x = 0 ; x < width; x++) {
65+ if (bitmap[y][x] != rgba (0 , 0 , 0 , 0 )) {
66+ double rotatedX = ((x - rotationCenterX) * cosTheta - (y - rotationCenterY) * sinTheta);
67+ double rotatedY = ((x - rotationCenterX) * sinTheta + (y - rotationCenterY) * cosTheta);
68+
69+ if (firstPixel) {
70+ firstPixel = false ;
71+ minX = maxX = rotatedX;
72+ minY = maxY = rotatedY;
73+ } else {
74+ if (rotatedX < minX)
75+ minX = rotatedX;
76+ else if (rotatedX > maxX)
77+ maxX = rotatedX;
78+
79+ if (rotatedY < minY)
80+ minY = rotatedY;
81+ else if (rotatedY > maxY)
82+ maxY = rotatedY;
83+ }
84+ }
85+ }
86+ }
87+
88+ out->setLeft (x + minX);
89+ out->setTop (y + maxY);
90+ out->setRight (x + maxX);
91+ out->setBottom (y + minY);
92+ }
0 commit comments