Skip to content

Commit 4b4ad04

Browse files
authored
Merge pull request #489 from scratchcpp/fix_sprite_fencing
Fix #469: Fix sprite fencing
2 parents 4f51860 + 68a46f3 commit 4b4ad04

File tree

7 files changed

+57
-11
lines changed

7 files changed

+57
-11
lines changed

include/scratchcpp/ispritehandler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ class LIBSCRATCHCPP_EXPORT ISpriteHandler
7070
* \note The rectangle must be relative to the stage, so make sure to use the sprite's coordinates.
7171
*/
7272
virtual Rect boundingRect() const = 0;
73+
74+
/*!
75+
* Used to get a less accurate bounding rectangle of the sprite
76+
* which is calculated by transforming the costume rectangle.
77+
* \note The rectangle must be relative to the stage, so make sure to use the sprite's coordinates.
78+
*/
79+
virtual Rect fastBoundingRect() const = 0;
7380
};
7481

7582
} // namespace libscratchcpp

include/scratchcpp/sprite.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class LIBSCRATCHCPP_EXPORT Sprite
7070
void setLayerOrder(int newLayerOrder) override;
7171

7272
Rect boundingRect() const;
73+
Rect fastBoundingRect() const;
7374
void keepInFence(double newX, double newY, double *fencedX, double *fencedY) const;
7475

7576
void setGraphicsEffectValue(IGraphicsEffect *effect, double value) override;

src/scratch/sprite.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,18 @@ Rect Sprite::boundingRect() const
350350
return impl->iface->boundingRect();
351351
}
352352

353+
/*!
354+
* Returns the less accurate bounding rectangle of the sprite
355+
* which is calculated by transforming the costume rectangle.
356+
*/
357+
Rect Sprite::fastBoundingRect() const
358+
{
359+
if (!impl->iface)
360+
return Rect(impl->x, impl->y, impl->x, impl->y);
361+
362+
return impl->iface->fastBoundingRect();
363+
}
364+
353365
/*!
354366
* Keeps the desired position within the stage.
355367
* \param[in] New desired X position.

src/scratch/sprite_p.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ void SpritePrivate::getFencedPosition(double x, double y, double *outX, double *
4848
Rect rect;
4949

5050
if (iface)
51-
rect = iface->boundingRect();
51+
rect = iface->fastBoundingRect();
52+
else
53+
rect = Rect(this->x, this->y, this->x, this->y);
5254

5355
double inset = std::floor(std::min(rect.width(), rect.height()) / 2);
5456

test/mocks/spritehandlermock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <scratchcpp/ispritehandler.h>
4+
#include <scratchcpp/rect.h>
45
#include <gmock/gmock.h>
56

67
using namespace libscratchcpp;
@@ -29,4 +30,5 @@ class SpriteHandlerMock : public ISpriteHandler
2930
MOCK_METHOD(void, onBubbleTextChanged, (const std::string &), (override));
3031

3132
MOCK_METHOD(Rect, boundingRect, (), (const, override));
33+
MOCK_METHOD(Rect, fastBoundingRect, (), (const, override));
3234
};

test/scratch_classes/sprite_test.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ TEST(SpriteTest, XY)
271271
EXPECT_CALL(engine, spriteFencingEnabled()).WillOnce(Return(true));
272272
EXPECT_CALL(engine, stageWidth()).WillOnce(Return(480));
273273
EXPECT_CALL(engine, stageHeight()).WillOnce(Return(360));
274-
EXPECT_CALL(handler, boundingRect()).WillOnce(Return(rect));
274+
EXPECT_CALL(handler, fastBoundingRect()).WillOnce(Return(rect));
275275
EXPECT_CALL(handler, onMoved);
276276
EXPECT_CALL(handler, onXChanged);
277277
sprite.setX(319);
@@ -280,7 +280,7 @@ TEST(SpriteTest, XY)
280280
EXPECT_CALL(engine, spriteFencingEnabled()).WillOnce(Return(true));
281281
EXPECT_CALL(engine, stageWidth()).WillOnce(Return(480));
282282
EXPECT_CALL(engine, stageHeight()).WillOnce(Return(360));
283-
EXPECT_CALL(handler, boundingRect()).WillOnce(Return(rect));
283+
EXPECT_CALL(handler, fastBoundingRect()).WillOnce(Return(rect));
284284
EXPECT_CALL(handler, onMoved);
285285
EXPECT_CALL(handler, onXChanged);
286286
sprite.setX(75);
@@ -289,7 +289,7 @@ TEST(SpriteTest, XY)
289289
EXPECT_CALL(engine, spriteFencingEnabled()).WillOnce(Return(true));
290290
EXPECT_CALL(engine, stageWidth()).WillOnce(Return(480));
291291
EXPECT_CALL(engine, stageHeight()).WillOnce(Return(360));
292-
EXPECT_CALL(handler, boundingRect()).WillOnce(Return(rect));
292+
EXPECT_CALL(handler, fastBoundingRect()).WillOnce(Return(rect));
293293
EXPECT_CALL(handler, onMoved);
294294
EXPECT_CALL(handler, onXChanged);
295295
sprite.setX(400);
@@ -304,7 +304,7 @@ TEST(SpriteTest, XY)
304304
EXPECT_CALL(engine, spriteFencingEnabled()).WillOnce(Return(true));
305305
EXPECT_CALL(engine, stageWidth()).WillOnce(Return(480));
306306
EXPECT_CALL(engine, stageHeight()).WillOnce(Return(360));
307-
EXPECT_CALL(handler, boundingRect()).WillOnce(Return(rect));
307+
EXPECT_CALL(handler, fastBoundingRect()).WillOnce(Return(rect));
308308
EXPECT_CALL(handler, onMoved);
309309
EXPECT_CALL(handler, onXChanged);
310310
sprite.setX(-400);
@@ -319,7 +319,7 @@ TEST(SpriteTest, XY)
319319
EXPECT_CALL(engine, spriteFencingEnabled()).WillOnce(Return(true));
320320
EXPECT_CALL(engine, stageWidth()).WillOnce(Return(480));
321321
EXPECT_CALL(engine, stageHeight()).WillOnce(Return(360));
322-
EXPECT_CALL(handler, boundingRect()).WillOnce(Return(rect));
322+
EXPECT_CALL(handler, fastBoundingRect()).WillOnce(Return(rect));
323323
EXPECT_CALL(handler, onMoved);
324324
EXPECT_CALL(handler, onYChanged);
325325
sprite.setY(150);
@@ -328,7 +328,7 @@ TEST(SpriteTest, XY)
328328
EXPECT_CALL(engine, spriteFencingEnabled()).WillOnce(Return(true));
329329
EXPECT_CALL(engine, stageWidth()).WillOnce(Return(480));
330330
EXPECT_CALL(engine, stageHeight()).WillOnce(Return(360));
331-
EXPECT_CALL(handler, boundingRect()).WillOnce(Return(rect));
331+
EXPECT_CALL(handler, fastBoundingRect()).WillOnce(Return(rect));
332332
EXPECT_CALL(handler, onMoved);
333333
EXPECT_CALL(handler, onYChanged);
334334
sprite.setY(-103);
@@ -337,7 +337,7 @@ TEST(SpriteTest, XY)
337337
EXPECT_CALL(engine, spriteFencingEnabled()).WillOnce(Return(true));
338338
EXPECT_CALL(engine, stageWidth()).WillOnce(Return(480));
339339
EXPECT_CALL(engine, stageHeight()).WillOnce(Return(360));
340-
EXPECT_CALL(handler, boundingRect()).WillOnce(Return(rect));
340+
EXPECT_CALL(handler, fastBoundingRect()).WillOnce(Return(rect));
341341
EXPECT_CALL(handler, onMoved);
342342
EXPECT_CALL(handler, onYChanged);
343343
sprite.setY(340);
@@ -352,7 +352,7 @@ TEST(SpriteTest, XY)
352352
EXPECT_CALL(engine, spriteFencingEnabled()).WillOnce(Return(true));
353353
EXPECT_CALL(engine, stageWidth()).WillOnce(Return(480));
354354
EXPECT_CALL(engine, stageHeight()).WillOnce(Return(360));
355-
EXPECT_CALL(handler, boundingRect()).WillOnce(Return(rect));
355+
EXPECT_CALL(handler, fastBoundingRect()).WillOnce(Return(rect));
356356
EXPECT_CALL(handler, onMoved);
357357
EXPECT_CALL(handler, onYChanged);
358358
sprite.setY(-340);
@@ -602,6 +602,18 @@ TEST(SpriteTest, DefaultBoundingRect)
602602
ASSERT_EQ(rect.bottom(), -45.01);
603603
}
604604

605+
TEST(SpriteTest, DefaultFastBoundingRect)
606+
{
607+
Sprite sprite;
608+
sprite.setX(65.5);
609+
sprite.setY(-45.01);
610+
Rect rect = sprite.fastBoundingRect();
611+
ASSERT_EQ(rect.left(), 65.5);
612+
ASSERT_EQ(rect.top(), -45.01);
613+
ASSERT_EQ(rect.right(), 65.5);
614+
ASSERT_EQ(rect.bottom(), -45.01);
615+
}
616+
605617
TEST(SpriteTest, GraphicsEffects)
606618
{
607619
Sprite sprite;

test/target_interfaces/ispritehandler_test.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ TEST_F(ISpriteHandlerTest, X)
6565
{
6666
EXPECT_CALL(m_handler, onMoved(0, 0, 189.46, 0));
6767
EXPECT_CALL(m_handler, onXChanged(189.46)).Times(1);
68-
EXPECT_CALL(m_handler, boundingRect()).WillOnce(Return(Rect()));
68+
EXPECT_CALL(m_handler, fastBoundingRect()).WillOnce(Return(Rect()));
6969
EXPECT_CALL(m_engine, spriteFencingEnabled()).WillOnce(Return(true));
7070
EXPECT_CALL(m_engine, stageWidth()).WillOnce(Return(480));
7171
EXPECT_CALL(m_engine, stageHeight()).WillOnce(Return(360));
@@ -83,7 +83,7 @@ TEST_F(ISpriteHandlerTest, Y)
8383
{
8484
EXPECT_CALL(m_handler, onMoved(0, 0, 0, -153.7)).Times(1);
8585
EXPECT_CALL(m_handler, onYChanged(-153.7)).Times(1);
86-
EXPECT_CALL(m_handler, boundingRect()).WillOnce(Return(Rect()));
86+
EXPECT_CALL(m_handler, fastBoundingRect()).WillOnce(Return(Rect()));
8787
EXPECT_CALL(m_engine, spriteFencingEnabled()).WillOnce(Return(true));
8888
EXPECT_CALL(m_engine, stageWidth()).WillOnce(Return(480));
8989
EXPECT_CALL(m_engine, stageHeight()).WillOnce(Return(360));
@@ -199,3 +199,13 @@ TEST_F(ISpriteHandlerTest, BoundingRect)
199199
ASSERT_EQ(rect.right(), 20.5);
200200
ASSERT_EQ(rect.bottom(), -0.48);
201201
}
202+
203+
TEST_F(ISpriteHandlerTest, FastBoundingRect)
204+
{
205+
EXPECT_CALL(m_handler, fastBoundingRect()).WillOnce(Return(Rect(-44.6, 89.1, 20.5, -0.48)));
206+
Rect rect = m_sprite.fastBoundingRect();
207+
ASSERT_EQ(rect.left(), -44.6);
208+
ASSERT_EQ(rect.top(), 89.1);
209+
ASSERT_EQ(rect.right(), 20.5);
210+
ASSERT_EQ(rect.bottom(), -0.48);
211+
}

0 commit comments

Comments
 (0)