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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ target_sources(scratchcpp
include/scratchcpp/keyevent.h
include/scratchcpp/iimageformat.h
include/scratchcpp/iimageformatfactory.h
include/scratchcpp/rect.h
)

add_library(zip SHARED
Expand Down
39 changes: 39 additions & 0 deletions include/scratchcpp/rect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "global.h"
#include "spimpl.h"

namespace libscratchcpp
{

class RectPrivate;

/*! The Rect class represents a rectangle. */
class LIBSCRATCHCPP_EXPORT Rect
{
public:
Rect(double left, double top, double right, double bottom);
Rect();

double left() const;
void setLeft(double left);

double top() const;
void setTop(double top);

double right() const;
void setRight(double right);

double bottom() const;
void setBottom(double bottom);

double width() const;
double height() const;

private:
spimpl::impl_ptr<RectPrivate> impl;
};

} // namespace libscratchcpp
3 changes: 3 additions & 0 deletions include/scratchcpp/sprite.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace libscratchcpp
{

class ISpriteHandler;
class Rect;
class SpritePrivate;

/*! \brief The Sprite class represents a Scratch sprite. */
Expand Down Expand Up @@ -62,6 +63,8 @@ class LIBSCRATCHCPP_EXPORT Sprite : public Target
void setRotationStyle(const std::string &newRotationStyle);
void setRotationStyle(const char *newRotationStyle);

Rect boundingRect() const;

private:
Target *dataSource() const override;

Expand Down
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ target_sources(scratchcpp
scratchconfiguration.cpp
scratchconfiguration_p.cpp
scratchconfiguration_p.h
rect.cpp
rect_p.cpp
rect_p.h
)

add_subdirectory(blocks)
Expand Down
79 changes: 79 additions & 0 deletions src/rect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: Apache-2.0

#include <scratchcpp/rect.h>
#include <cmath>
#include "rect_p.h"

using namespace libscratchcpp;

/*! Constructs Rect. */
Rect::Rect(double left, double top, double right, double bottom) :
impl(spimpl::make_impl<RectPrivate>(left, top, right, bottom))
{
}

/*! \copydoc Rect() */
Rect::Rect() :
impl(spimpl::make_impl<RectPrivate>())
{
}

/*! Returns the x-coordinate of the left edge. */
double Rect::left() const
{
return impl->left;
}

/*! Sets the x-coordinate of the left edge. */
void Rect::setLeft(double left)
{
impl->left = left;
}

/*! Returns the y-coordinate of the top edge. */
double Rect::top() const
{
return impl->top;
}

/*! Sets the y-coordinate of the top edge. */
void Rect::setTop(double top)
{
impl->top = top;
}

/*! Returns the x-coordinate of the right edge. */
double Rect::right() const
{
return impl->right;
}

/*! Sets the x-coordinate of the right edge. */
void Rect::setRight(double right)
{
impl->right = right;
}

/*! Returns the y-coordinate of the bottom edge. */
double Rect::bottom() const
{
return impl->bottom;
}

/*! Sets the y-coordinate of the bottom edge. */
void Rect::setBottom(double bottom)
{
impl->bottom = bottom;
}

/*! Returns the width of the rectangle. */
double Rect::width() const
{
return std::abs(impl->right - impl->left);
}

/*! Returns the height of the rectangle. */
double Rect::height() const
{
return std::abs(impl->top - impl->bottom);
}
20 changes: 20 additions & 0 deletions src/rect_p.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: Apache-2.0

#include "rect_p.h"

namespace libscratchcpp
{

RectPrivate::RectPrivate(double left, double top, double right, double bottom) :
left(left),
top(top),
right(right),
bottom(bottom)
{
}

RectPrivate::RectPrivate()
{
}

} // namespace libscratchcpp
19 changes: 19 additions & 0 deletions src/rect_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: Apache-2.0

#pragma once

namespace libscratchcpp
{

struct RectPrivate
{
RectPrivate(double left, double top, double right, double bottom);
RectPrivate();

double left = 0;
double top = 0;
double right = 0;
double bottom = 0;
};

} // namespace libscratchcpp
12 changes: 11 additions & 1 deletion src/scratch/sprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <scratchcpp/variable.h>
#include <scratchcpp/list.h>
#include <scratchcpp/costume.h>
#include <scratchcpp/rect.h>
#include <cassert>

#include "sprite_p.h"
Expand All @@ -15,7 +16,7 @@ using namespace libscratchcpp;
/*! Constructs Sprite. */
Sprite::Sprite() :
Target(),
impl(spimpl::make_unique_impl<SpritePrivate>())
impl(spimpl::make_unique_impl<SpritePrivate>(this))
{
}

Expand Down Expand Up @@ -297,6 +298,15 @@ void Sprite::setRotationStyle(const char *newRotationStyle)
setRotationStyle(std::string(newRotationStyle));
}

/*! Returns the bounding rectangle of the sprite. */
Rect Sprite::boundingRect() const
{
Rect ret;
impl->getBoundingRect(&ret);

return ret;
}

Target *Sprite::dataSource() const
{
return impl->cloneRoot;
Expand Down
64 changes: 63 additions & 1 deletion src/scratch/sprite_p.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
// SPDX-License-Identifier: Apache-2.0

#include <scratchcpp/ispritehandler.h>
#include <scratchcpp/rect.h>
#include <scratchcpp/costume.h>
#include <cmath>

#include "sprite_p.h"

using namespace libscratchcpp;

SpritePrivate::SpritePrivate()
static const double pi = std::acos(-1); // TODO: Use std::numbers::pi in C++20

SpritePrivate::SpritePrivate(Sprite *sprite) :
sprite(sprite)
{
}

Expand All @@ -28,3 +34,59 @@ void SpritePrivate::setCostumeData(const char *data)
if (iface)
iface->onCostumeChanged(data);
}

void SpritePrivate::getBoundingRect(Rect *out) const
{
assert(out);
assert(sprite);
// TODO: Make currentCostume() return the costume
auto costume = sprite->costumeAt(sprite->currentCostume() - 1);

if (!costume) {
out->setLeft(0);
out->setTop(0);
out->setRight(0);
out->setBottom(0);
return;
}

double cosTheta = std::cos((90 - direction) * pi / 180);
double sinTheta = std::sin((90 - direction) * pi / 180);
double maxX = 0, maxY = 0, minX = 0, minY = 0;
bool firstPixel = true;
unsigned int width = costume->width();
unsigned int height = costume->height();
double rotationCenterX = width / 2.0 + costume->rotationCenterX();
double rotationCenterY = height / 2.0 + costume->rotationCenterY();
Rgb **bitmap = costume->bitmap();

for (unsigned int y = 0; y < height; y++) {
for (unsigned int x = 0; x < width; x++) {
if (bitmap[y][x] != rgba(0, 0, 0, 0)) {
double rotatedX = ((x - rotationCenterX) * cosTheta - (y - rotationCenterY) * sinTheta);
double rotatedY = ((x - rotationCenterX) * sinTheta + (y - rotationCenterY) * cosTheta);

if (firstPixel) {
firstPixel = false;
minX = maxX = rotatedX;
minY = maxY = rotatedY;
} else {
if (rotatedX < minX)
minX = rotatedX;
else if (rotatedX > maxX)
maxX = rotatedX;

if (rotatedY < minY)
minY = rotatedY;
else if (rotatedY > maxY)
maxY = rotatedY;
}
}
}
}

out->setLeft(x + minX);
out->setTop(y + maxY);
out->setRight(x + maxX);
out->setBottom(y + minY);
}
6 changes: 5 additions & 1 deletion src/scratch/sprite_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@
namespace libscratchcpp
{

class Rect;

struct SpritePrivate
{
SpritePrivate();
SpritePrivate(Sprite *sprite);
SpritePrivate(const SpritePrivate &) = delete;

void removeClone(Sprite *clone);

void setCostumeData(const char *data);
void getBoundingRect(Rect *out) const;

Sprite *sprite = nullptr;
ISpriteHandler *iface = nullptr;
Sprite *cloneRoot = nullptr;
Sprite *cloneParent = nullptr;
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ add_subdirectory(clock)
add_subdirectory(timer)
add_subdirectory(randomgenerator)
add_subdirectory(imageformats)
add_subdirectory(rect)
12 changes: 12 additions & 0 deletions test/rect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
add_executable(
rect_test
rect_test.cpp
)

target_link_libraries(
rect_test
GTest::gtest_main
scratchcpp
)

gtest_discover_tests(rect_test)
Loading