Skip to content

Commit 2ce9880

Browse files
committed
Add getInitialPosition() method to Monitor
1 parent cead8ff commit 2ce9880

File tree

6 files changed

+75
-0
lines changed

6 files changed

+75
-0
lines changed

include/scratchcpp/monitor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
#include <scratchcpp/entity.h>
66

7+
#include <vector>
8+
79
namespace libscratchcpp
810
{
911

1012
class Block;
1113
class Sprite;
14+
class Rect;
1215
class MonitorPrivate;
1316

1417
/*! \brief The Monitor class represents a stage monitor. */
@@ -60,6 +63,8 @@ class LIBSCRATCHCPP_EXPORT Monitor : public Entity
6063
bool discrete() const;
6164
void setDiscrete(bool discrete);
6265

66+
static Rect getInitialPosition(const std::vector<std::shared_ptr<Monitor>> &other, int monitorWidth, int monitorHeight);
67+
6368
private:
6469
spimpl::unique_impl_ptr<MonitorPrivate> impl;
6570
};

src/scratch/monitor.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33
#include <scratchcpp/monitor.h>
44
#include <scratchcpp/block.h>
55
#include <scratchcpp/sprite.h>
6+
#include <scratchcpp/rect.h>
67

78
#include "monitor_p.h"
9+
#include "engine/internal/randomgenerator.h"
810

911
using namespace libscratchcpp;
1012

13+
static const int PADDING = 5;
14+
static const int SCREEN_WIDTH = 400;
15+
static const int SCREEN_HEIGHT = 300;
16+
static const int SCREEN_EDGE_BUFFER = 40;
17+
1118
/*! Constructs Monitor. */
1219
Monitor::Monitor(const std::string &id, const std::string &opcode) :
1320
Entity(id),
@@ -146,3 +153,16 @@ void Monitor::setDiscrete(bool discrete)
146153
{
147154
impl->discrete = discrete;
148155
}
156+
157+
/*! Returns the initial position of a monitor. */
158+
Rect Monitor::getInitialPosition(const std::vector<std::shared_ptr<Monitor>> &other, int monitorWidth, int monitorHeight)
159+
{
160+
// TODO: Implement this like Scratch has: https://github.com/scratchfoundation/scratch-gui/blob/010e27937ecff531f23bfcf3c711cd6e565cc7f9/src/reducers/monitor-layout.js#L161-L243
161+
// Place the monitor randomly
162+
if (!MonitorPrivate::rng)
163+
MonitorPrivate::rng = RandomGenerator::instance().get();
164+
165+
const double randX = std::ceil(MonitorPrivate::rng->randintDouble(0, SCREEN_WIDTH / 2.0));
166+
const double randY = std::ceil(MonitorPrivate::rng->randintDouble(0, SCREEN_HEIGHT - SCREEN_EDGE_BUFFER));
167+
return Rect(randX, randY, randX + monitorWidth, randY + monitorHeight);
168+
}

src/scratch/monitor_p.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
using namespace libscratchcpp;
88

9+
IRandomGenerator *MonitorPrivate::rng = nullptr;
10+
911
MonitorPrivate::MonitorPrivate(const std::string &opcode) :
1012
block(std::make_shared<Block>("", opcode))
1113
{

src/scratch/monitor_p.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace libscratchcpp
88
{
99

1010
class Block;
11+
class IRandomGenerator;
1112

1213
struct MonitorPrivate
1314
{
@@ -24,6 +25,7 @@ struct MonitorPrivate
2425
double sliderMin = 0;
2526
double sliderMax = 0;
2627
bool discrete = false;
28+
static IRandomGenerator *rng;
2729
};
2830

2931
} // namespace libscratchcpp

test/scratch_classes/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ add_executable(
227227
target_link_libraries(
228228
monitor_test
229229
GTest::gtest_main
230+
GTest::gmock_main
230231
scratchcpp
232+
scratchcpp_mocks
231233
)
232234

233235
gtest_discover_tests(monitor_test)

test/scratch_classes/monitor_test.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
#include <scratchcpp/monitor.h>
22
#include <scratchcpp/block.h>
33
#include <scratchcpp/sprite.h>
4+
#include <scratchcpp/rect.h>
5+
#include <scratch/monitor_p.h>
6+
#include <randomgeneratormock.h>
47

58
#include "../common.h"
69

710
using namespace libscratchcpp;
811

12+
using ::testing::Return;
13+
14+
static const int PADDING = 5;
15+
static const int SCREEN_WIDTH = 400;
16+
static const int SCREEN_HEIGHT = 300;
17+
static const int SCREEN_EDGE_BUFFER = 40;
18+
919
TEST(MonitorTest, Constructors)
1020
{
1121
Monitor monitor("abc", "test");
@@ -141,3 +151,37 @@ TEST(MonitorTest, Discrete)
141151
monitor.setDiscrete(false);
142152
ASSERT_FALSE(monitor.discrete());
143153
}
154+
155+
TEST(MonitorTest, GetInitialPosition)
156+
{
157+
std::vector<std::shared_ptr<Monitor>> monitors;
158+
const int width = 100;
159+
const int height = 200;
160+
161+
auto monitor1 = std::make_shared<Monitor>("", "");
162+
monitor1->setWidth(PADDING);
163+
monitor1->setHeight(height);
164+
monitor1->setX(100);
165+
monitor1->setY(0);
166+
monitors.push_back(monitor1);
167+
168+
auto monitor2 = std::make_shared<Monitor>("", "");
169+
monitor2->setWidth(width);
170+
monitor2->setHeight(height + PADDING - 100);
171+
monitor2->setX(0);
172+
monitor2->setY(100);
173+
monitors.push_back(monitor2);
174+
175+
RandomGeneratorMock rng;
176+
MonitorPrivate::rng = &rng;
177+
178+
EXPECT_CALL(rng, randintDouble(0, SCREEN_WIDTH / 2.0)).WillOnce(Return(SCREEN_WIDTH / 4.5));
179+
EXPECT_CALL(rng, randintDouble(0, SCREEN_HEIGHT - SCREEN_EDGE_BUFFER)).WillOnce(Return(SCREEN_HEIGHT - SCREEN_EDGE_BUFFER * 2.3));
180+
Rect rect = Monitor::getInitialPosition(monitors, width, height);
181+
ASSERT_EQ(rect.left(), std::ceil(SCREEN_WIDTH / 4.5));
182+
ASSERT_EQ(rect.top(), std::ceil(SCREEN_HEIGHT - SCREEN_EDGE_BUFFER * 2.3));
183+
ASSERT_EQ(rect.width(), width);
184+
ASSERT_EQ(rect.height(), height);
185+
186+
MonitorPrivate::rng = nullptr;
187+
}

0 commit comments

Comments
 (0)