Skip to content

Commit 64ad83d

Browse files
committed
RenderedTarget: Cache transformed hull points
Resolves: #118
1 parent e29a6b9 commit 64ad83d

File tree

2 files changed

+49
-19
lines changed

2 files changed

+49
-19
lines changed

src/renderedtarget.cpp

+45-18
Original file line numberDiff line numberDiff line change
@@ -371,31 +371,16 @@ void RenderedTarget::setHeight(qreal height)
371371
Rect RenderedTarget::getBounds() const
372372
{
373373
// https://github.com/scratchfoundation/scratch-render/blob/c3ede9c3d54769730c7b023021511e2aba167b1f/src/Rectangle.js#L33-L55
374-
if (!m_costume || !m_skin || !m_texture.isValid() || !m_cpuTexture.isValid())
375-
return Rect(m_x, m_y, m_x, m_y);
376-
377-
const double textureScale = m_skin->getTextureScale(m_cpuTexture);
378-
const double bitmapRes = m_costume->bitmapResolution();
379-
const double width = m_cpuTexture.width() * m_size / textureScale;
380-
const double height = m_cpuTexture.height() * m_size / textureScale;
381-
const double originX = m_costume->rotationCenterX() * m_size / bitmapRes - width / 2;
382-
const double originY = -m_costume->rotationCenterY() * m_size / bitmapRes + height / 2;
383-
const double rot = -rotation() * pi / 180;
384-
const double sinRot = std::sin(rot);
385-
const double cosRot = std::cos(rot);
386374
double left = std::numeric_limits<double>::infinity();
387375
double top = -std::numeric_limits<double>::infinity();
388376
double right = -std::numeric_limits<double>::infinity();
389377
double bottom = std::numeric_limits<double>::infinity();
390378

391-
const std::vector<QPoint> &points = hullPoints();
379+
const std::vector<QPointF> &points = transformedHullPoints();
392380

393381
for (const QPointF &point : points) {
394-
double x = point.x() * m_size / textureScale / bitmapRes - width / 2;
395-
double y = height / 2 - point.y() * m_size / textureScale / bitmapRes;
396-
const QPointF transformed = transformPoint(x, y, originX, originY, sinRot, cosRot);
397-
x = transformed.x() * (m_mirrorHorizontally ? -1 : 1);
398-
y = transformed.y();
382+
const double x = point.x();
383+
const double y = point.y();
399384

400385
if (x < left)
401386
left = x;
@@ -733,6 +718,8 @@ void RenderedTarget::calculatePos()
733718
else
734719
setTransformOrigin(QQuickItem::Center);
735720
}
721+
722+
m_transformedHullDirty = true;
736723
}
737724

738725
void RenderedTarget::calculateRotation()
@@ -764,6 +751,8 @@ void RenderedTarget::calculateRotation()
764751
if (m_mirrorHorizontally != oldMirrorHorizontally)
765752
emit mirrorHorizontallyChanged();
766753
}
754+
755+
m_transformedHullDirty = true;
767756
}
768757

769758
void RenderedTarget::calculateSize()
@@ -779,6 +768,8 @@ void RenderedTarget::calculateSize()
779768

780769
if (wasValid && m_cpuTexture.handle() != oldTexture)
781770
m_convexHullDirty = true;
771+
772+
m_transformedHullDirty = true;
782773
}
783774
}
784775

@@ -811,6 +802,42 @@ void RenderedTarget::updateHullPoints()
811802
// TODO: Apply graphic effects (#117)
812803
}
813804

805+
const std::vector<QPointF> &RenderedTarget::transformedHullPoints() const
806+
{
807+
// https://github.com/scratchfoundation/scratch-render/blob/9fe90e8f4c2da35d4684359f84b69c264d884133/src/Drawable.js#L594-L616
808+
if (!m_transformedHullDirty)
809+
return m_transformedHullPoints;
810+
811+
m_transformedHullPoints.clear();
812+
813+
if (!m_costume || !m_skin || !m_texture.isValid() || !m_cpuTexture.isValid())
814+
return m_transformedHullPoints;
815+
816+
const double textureScale = m_skin->getTextureScale(m_cpuTexture);
817+
const double bitmapRes = m_costume->bitmapResolution();
818+
const double width = m_cpuTexture.width() * m_size / textureScale;
819+
const double height = m_cpuTexture.height() * m_size / textureScale;
820+
const double originX = m_costume->rotationCenterX() * m_size / bitmapRes - width / 2;
821+
const double originY = -m_costume->rotationCenterY() * m_size / bitmapRes + height / 2;
822+
const double rot = -rotation() * pi / 180;
823+
const double sinRot = std::sin(rot);
824+
const double cosRot = std::cos(rot);
825+
826+
const std::vector<QPoint> &points = hullPoints();
827+
m_transformedHullPoints.reserve(points.size());
828+
829+
for (const QPoint &point : points) {
830+
double x = point.x() * m_size / textureScale / bitmapRes - width / 2;
831+
double y = height / 2 - point.y() * m_size / textureScale / bitmapRes;
832+
const QPointF transformed = transformPoint(x, y, originX, originY, sinRot, cosRot);
833+
x = transformed.x() * (m_mirrorHorizontally ? -1 : 1);
834+
y = transformed.y();
835+
m_transformedHullPoints.push_back(QPointF(x, y));
836+
}
837+
838+
return m_transformedHullPoints;
839+
}
840+
814841
bool RenderedTarget::containsLocalPoint(const QPointF &point) const
815842
{
816843
return textureManager()->textureContainsPoint(m_cpuTexture, point, m_graphicEffects);

src/renderedtarget.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class RenderedTarget : public IRenderedTarget
124124
void handleSceneMouseMove(qreal x, qreal y);
125125
bool convexHullPointsNeeded() const;
126126
void updateHullPoints();
127+
const std::vector<QPointF> &transformedHullPoints() const;
127128
bool containsLocalPoint(const QPointF &point) const;
128129
QPointF transformPoint(double scratchX, double scratchY, double originX, double originY, double rot) const;
129130
QPointF transformPoint(double scratchX, double scratchY, double originX, double originY, double sinRot, double cosRot) const;
@@ -169,7 +170,9 @@ class RenderedTarget : public IRenderedTarget
169170
qreal m_maximumHeight = std::numeric_limits<double>::infinity();
170171
bool m_convexHullDirty = true;
171172
std::vector<QPoint> m_hullPoints;
172-
bool m_clicked = false; // left mouse button only!
173+
bool m_transformedHullDirty = true;
174+
mutable std::vector<QPointF> m_transformedHullPoints; // NOTE: Use transformedHullPoints();
175+
bool m_clicked = false; // left mouse button only!
173176
double m_dragX = 0;
174177
double m_dragY = 0;
175178
double m_dragDeltaX = 0;

0 commit comments

Comments
 (0)