Skip to content

Commit 6f0f10e

Browse files
authored
Merge pull request #52 from scratchcpp/rendering_improvements
Rendering improvements
2 parents 2e4f970 + 2de1c32 commit 6f0f10e

File tree

4 files changed

+244
-29
lines changed

4 files changed

+244
-29
lines changed

ScratchCPPGui/renderedtarget.cpp

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,30 @@
1313
using namespace scratchcppgui;
1414
using namespace libscratchcpp;
1515

16+
static const double SVG_SCALE_LIMIT = 0.1; // the maximum viewport dimensions are multiplied by this
17+
1618
RenderedTarget::RenderedTarget(QNanoQuickItem *parent) :
1719
IRenderedTarget(parent)
1820
{
21+
// Get maximum viewport dimensions
22+
QOpenGLContext context;
23+
context.create();
24+
Q_ASSERT(context.isValid());
25+
26+
if (context.isValid()) {
27+
QOffscreenSurface surface;
28+
surface.create();
29+
Q_ASSERT(surface.isValid());
30+
31+
if (surface.isValid()) {
32+
context.makeCurrent(&surface);
33+
GLint dims[2];
34+
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
35+
m_maximumWidth = dims[0] * SVG_SCALE_LIMIT;
36+
m_maximumHeight = dims[1] * SVG_SCALE_LIMIT;
37+
context.doneCurrent();
38+
}
39+
}
1940
}
2041

2142
void RenderedTarget::loadProperties()
@@ -31,6 +52,9 @@ void RenderedTarget::loadProperties()
3152
// Visibility
3253
m_visible = sprite->visible();
3354

55+
m_size = sprite->size() / 100;
56+
updateCostumeData();
57+
3458
if (m_visible) {
3559
// Direction
3660
switch (sprite->rotationStyle()) {
@@ -54,18 +78,19 @@ void RenderedTarget::loadProperties()
5478
}
5579

5680
// Coordinates
57-
double size = sprite->size() / 100;
58-
m_x = static_cast<double>(m_engine->stageWidth()) / 2 + sprite->x() - m_costume->rotationCenterX() * size / m_costume->bitmapResolution() * (m_newMirrorHorizontally ? -1 : 1);
59-
m_y = static_cast<double>(m_engine->stageHeight()) / 2 - sprite->y() - m_costume->rotationCenterY() * size / m_costume->bitmapResolution();
60-
m_originX = m_costume->rotationCenterX() * size / m_costume->bitmapResolution();
61-
m_originY = m_costume->rotationCenterY() * size / m_costume->bitmapResolution();
81+
double clampedSize = std::min(m_size, m_maxSize);
82+
m_x = static_cast<double>(m_engine->stageWidth()) / 2 + sprite->x() - m_costume->rotationCenterX() * clampedSize / m_costume->bitmapResolution() * (m_newMirrorHorizontally ? -1 : 1);
83+
m_y = static_cast<double>(m_engine->stageHeight()) / 2 - sprite->y() - m_costume->rotationCenterY() * clampedSize / m_costume->bitmapResolution();
84+
m_originX = m_costume->rotationCenterX() * clampedSize / m_costume->bitmapResolution();
85+
m_originY = m_costume->rotationCenterY() * clampedSize / m_costume->bitmapResolution();
6286

6387
// Layer
6488
m_z = sprite->layerOrder();
6589
}
6690

6791
mutex.unlock();
6892
} else if (m_stageModel) {
93+
updateCostumeData();
6994
m_x = static_cast<double>(m_engine->stageWidth()) / 2 - m_costume->rotationCenterX() / m_costume->bitmapResolution();
7095
m_y = static_cast<double>(m_engine->stageHeight()) / 2 - m_costume->rotationCenterY() / m_costume->bitmapResolution();
7196
m_originX = m_costume->rotationCenterX() / m_costume->bitmapResolution();
@@ -79,13 +104,8 @@ void RenderedTarget::loadCostume(Costume *costume)
79104
return;
80105

81106
m_costumeMutex.lock();
82-
m_imageChanged = true;
83-
84-
if (costume->dataFormat() == "svg") {
85-
if (costume != m_costume)
86-
m_svgRenderer.load(QByteArray::fromRawData(static_cast<const char *>(costume->data()), costume->dataSize()));
87-
}
88-
107+
m_loadCostume = true;
108+
m_costumeChanged = (costume != m_costume);
89109
m_costume = costume;
90110
m_costumeMutex.unlock();
91111
}
@@ -97,16 +117,23 @@ void RenderedTarget::updateProperties()
97117

98118
if (m_visible) {
99119
if (m_imageChanged) {
100-
doLoadCostume();
101120
update();
102121
m_imageChanged = false;
103122
}
104123

105124
setX(m_x);
106125
setY(m_y);
107126
setZ(m_z);
127+
setWidth(m_width);
128+
setHeight(m_height);
108129
setRotation(m_rotation);
109130
setTransformOriginPoint(QPointF(m_originX, m_originY));
131+
Q_ASSERT(m_maxSize > 0);
132+
133+
if (!m_stageModel && (m_size > m_maxSize) && (m_maxSize != 0))
134+
setScale(m_size / m_maxSize);
135+
else
136+
setScale(1);
110137

111138
if (m_newMirrorHorizontally != m_mirrorHorizontally) {
112139
m_mirrorHorizontally = m_newMirrorHorizontally;
@@ -194,6 +221,28 @@ QNanoQuickItemPainter *RenderedTarget::createItemPainter() const
194221
return new TargetPainter();
195222
}
196223

224+
void RenderedTarget::updateCostumeData()
225+
{
226+
// Costume
227+
m_costumeMutex.lock();
228+
229+
if (m_loadCostume) {
230+
m_loadCostume = false;
231+
m_imageChanged = true;
232+
233+
if (m_costumeChanged) {
234+
m_costumeChanged = false;
235+
assert(m_costume);
236+
237+
if (m_costume->dataFormat() == "svg")
238+
m_svgRenderer.load(QByteArray::fromRawData(static_cast<const char *>(m_costume->data()), m_costume->dataSize()));
239+
}
240+
}
241+
242+
m_costumeMutex.unlock();
243+
doLoadCostume();
244+
}
245+
197246
void RenderedTarget::doLoadCostume()
198247
{
199248
m_costumeMutex.lock();
@@ -240,13 +289,9 @@ void RenderedTarget::paintSvg(QNanoPainter *painter)
240289
QSurface *oldSurface = context->surface();
241290
context->makeCurrent(&surface);
242291

243-
const QRectF drawRect(0, 0, width(), height());
292+
const QRectF drawRect(0, 0, std::min(width(), m_maximumWidth), std::min(height(), m_maximumHeight));
244293
const QSize drawRectSize = drawRect.size().toSize();
245294

246-
/*QOpenGLFramebufferObjectFormat fboFormat;
247-
fboFormat.setSamples(16);
248-
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);*/
249-
250295
QOpenGLPaintDevice device(drawRectSize);
251296
QPainter qPainter;
252297
qPainter.begin(&device);
@@ -262,15 +307,16 @@ void RenderedTarget::calculateSize(Target *target, double costumeWidth, double c
262307
{
263308
if (m_costume) {
264309
double bitmapRes = m_costume->bitmapResolution();
310+
m_maxSize = std::min(m_maximumWidth / costumeWidth, m_maximumHeight / costumeHeight);
265311
Sprite *sprite = dynamic_cast<Sprite *>(target);
266312

267313
if (sprite) {
268-
double size = sprite->size();
269-
setWidth(costumeWidth * size / 100 / bitmapRes);
270-
setHeight(costumeHeight * size / 100 / bitmapRes);
314+
double clampedSize = std::min(m_size, m_maxSize);
315+
m_width = costumeWidth * clampedSize / bitmapRes;
316+
m_height = costumeHeight * clampedSize / bitmapRes;
271317
} else {
272-
setWidth(costumeWidth / bitmapRes);
273-
setHeight(costumeHeight / bitmapRes);
318+
m_width = costumeWidth / bitmapRes;
319+
m_height = costumeHeight / bitmapRes;
274320
}
275321
}
276322
}

ScratchCPPGui/renderedtarget.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class RenderedTarget : public IRenderedTarget
7070
QNanoQuickItemPainter *createItemPainter() const override;
7171

7272
private:
73+
void updateCostumeData();
7374
void doLoadCostume();
7475
void calculateSize(libscratchcpp::Target *target, double costumeWidth, double costumeHeight);
7576

@@ -82,16 +83,24 @@ class RenderedTarget : public IRenderedTarget
8283
QString m_bitmapUniqueKey;
8384
QMutex m_costumeMutex;
8485
QMutex mutex;
86+
bool m_loadCostume = false;
87+
bool m_costumeChanged = false;
8588
bool m_imageChanged = false;
8689
bool m_visible = true;
90+
double m_size = 1;
91+
double m_maxSize = 1;
8792
double m_x = 0;
8893
double m_y = 0;
8994
double m_z = 0;
95+
double m_width = 0;
96+
double m_height = 0;
9097
double m_rotation = 0;
9198
bool m_mirrorHorizontally = false;
9299
bool m_newMirrorHorizontally = false;
93100
double m_originX = 0;
94101
double m_originY = 0;
102+
qreal m_maximumWidth = std::numeric_limits<double>::infinity();
103+
qreal m_maximumHeight = std::numeric_limits<double>::infinity();
95104
};
96105

97106
} // namespace scratchcppgui

0 commit comments

Comments
 (0)