Skip to content

Rendering improvements #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 23, 2023
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
92 changes: 69 additions & 23 deletions ScratchCPPGui/renderedtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,30 @@
using namespace scratchcppgui;
using namespace libscratchcpp;

static const double SVG_SCALE_LIMIT = 0.1; // the maximum viewport dimensions are multiplied by this

RenderedTarget::RenderedTarget(QNanoQuickItem *parent) :
IRenderedTarget(parent)
{
// Get maximum viewport dimensions
QOpenGLContext context;
context.create();
Q_ASSERT(context.isValid());

if (context.isValid()) {
QOffscreenSurface surface;
surface.create();
Q_ASSERT(surface.isValid());

if (surface.isValid()) {
context.makeCurrent(&surface);
GLint dims[2];
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
m_maximumWidth = dims[0] * SVG_SCALE_LIMIT;
m_maximumHeight = dims[1] * SVG_SCALE_LIMIT;
context.doneCurrent();
}
}
}

void RenderedTarget::loadProperties()
Expand All @@ -31,6 +52,9 @@ void RenderedTarget::loadProperties()
// Visibility
m_visible = sprite->visible();

m_size = sprite->size() / 100;
updateCostumeData();

if (m_visible) {
// Direction
switch (sprite->rotationStyle()) {
Expand All @@ -54,18 +78,19 @@ void RenderedTarget::loadProperties()
}

// Coordinates
double size = sprite->size() / 100;
m_x = static_cast<double>(m_engine->stageWidth()) / 2 + sprite->x() - m_costume->rotationCenterX() * size / m_costume->bitmapResolution() * (m_newMirrorHorizontally ? -1 : 1);
m_y = static_cast<double>(m_engine->stageHeight()) / 2 - sprite->y() - m_costume->rotationCenterY() * size / m_costume->bitmapResolution();
m_originX = m_costume->rotationCenterX() * size / m_costume->bitmapResolution();
m_originY = m_costume->rotationCenterY() * size / m_costume->bitmapResolution();
double clampedSize = std::min(m_size, m_maxSize);
m_x = static_cast<double>(m_engine->stageWidth()) / 2 + sprite->x() - m_costume->rotationCenterX() * clampedSize / m_costume->bitmapResolution() * (m_newMirrorHorizontally ? -1 : 1);
m_y = static_cast<double>(m_engine->stageHeight()) / 2 - sprite->y() - m_costume->rotationCenterY() * clampedSize / m_costume->bitmapResolution();
m_originX = m_costume->rotationCenterX() * clampedSize / m_costume->bitmapResolution();
m_originY = m_costume->rotationCenterY() * clampedSize / m_costume->bitmapResolution();

// Layer
m_z = sprite->layerOrder();
}

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

m_costumeMutex.lock();
m_imageChanged = true;

if (costume->dataFormat() == "svg") {
if (costume != m_costume)
m_svgRenderer.load(QByteArray::fromRawData(static_cast<const char *>(costume->data()), costume->dataSize()));
}

m_loadCostume = true;
m_costumeChanged = (costume != m_costume);
m_costume = costume;
m_costumeMutex.unlock();
}
Expand All @@ -97,16 +117,23 @@ void RenderedTarget::updateProperties()

if (m_visible) {
if (m_imageChanged) {
doLoadCostume();
update();
m_imageChanged = false;
}

setX(m_x);
setY(m_y);
setZ(m_z);
setWidth(m_width);
setHeight(m_height);
setRotation(m_rotation);
setTransformOriginPoint(QPointF(m_originX, m_originY));
Q_ASSERT(m_maxSize > 0);

if (!m_stageModel && (m_size > m_maxSize) && (m_maxSize != 0))
setScale(m_size / m_maxSize);
else
setScale(1);

if (m_newMirrorHorizontally != m_mirrorHorizontally) {
m_mirrorHorizontally = m_newMirrorHorizontally;
Expand Down Expand Up @@ -194,6 +221,28 @@ QNanoQuickItemPainter *RenderedTarget::createItemPainter() const
return new TargetPainter();
}

void RenderedTarget::updateCostumeData()
{
// Costume
m_costumeMutex.lock();

if (m_loadCostume) {
m_loadCostume = false;
m_imageChanged = true;

if (m_costumeChanged) {
m_costumeChanged = false;
assert(m_costume);

if (m_costume->dataFormat() == "svg")
m_svgRenderer.load(QByteArray::fromRawData(static_cast<const char *>(m_costume->data()), m_costume->dataSize()));
}
}

m_costumeMutex.unlock();
doLoadCostume();
}

void RenderedTarget::doLoadCostume()
{
m_costumeMutex.lock();
Expand Down Expand Up @@ -240,13 +289,9 @@ void RenderedTarget::paintSvg(QNanoPainter *painter)
QSurface *oldSurface = context->surface();
context->makeCurrent(&surface);

const QRectF drawRect(0, 0, width(), height());
const QRectF drawRect(0, 0, std::min(width(), m_maximumWidth), std::min(height(), m_maximumHeight));
const QSize drawRectSize = drawRect.size().toSize();

/*QOpenGLFramebufferObjectFormat fboFormat;
fboFormat.setSamples(16);
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);*/

QOpenGLPaintDevice device(drawRectSize);
QPainter qPainter;
qPainter.begin(&device);
Expand All @@ -262,15 +307,16 @@ void RenderedTarget::calculateSize(Target *target, double costumeWidth, double c
{
if (m_costume) {
double bitmapRes = m_costume->bitmapResolution();
m_maxSize = std::min(m_maximumWidth / costumeWidth, m_maximumHeight / costumeHeight);
Sprite *sprite = dynamic_cast<Sprite *>(target);

if (sprite) {
double size = sprite->size();
setWidth(costumeWidth * size / 100 / bitmapRes);
setHeight(costumeHeight * size / 100 / bitmapRes);
double clampedSize = std::min(m_size, m_maxSize);
m_width = costumeWidth * clampedSize / bitmapRes;
m_height = costumeHeight * clampedSize / bitmapRes;
} else {
setWidth(costumeWidth / bitmapRes);
setHeight(costumeHeight / bitmapRes);
m_width = costumeWidth / bitmapRes;
m_height = costumeHeight / bitmapRes;
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions ScratchCPPGui/renderedtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class RenderedTarget : public IRenderedTarget
QNanoQuickItemPainter *createItemPainter() const override;

private:
void updateCostumeData();
void doLoadCostume();
void calculateSize(libscratchcpp::Target *target, double costumeWidth, double costumeHeight);

Expand All @@ -82,16 +83,24 @@ class RenderedTarget : public IRenderedTarget
QString m_bitmapUniqueKey;
QMutex m_costumeMutex;
QMutex mutex;
bool m_loadCostume = false;
bool m_costumeChanged = false;
bool m_imageChanged = false;
bool m_visible = true;
double m_size = 1;
double m_maxSize = 1;
double m_x = 0;
double m_y = 0;
double m_z = 0;
double m_width = 0;
double m_height = 0;
double m_rotation = 0;
bool m_mirrorHorizontally = false;
bool m_newMirrorHorizontally = false;
double m_originX = 0;
double m_originY = 0;
qreal m_maximumWidth = std::numeric_limits<double>::infinity();
qreal m_maximumHeight = std::numeric_limits<double>::infinity();
};

} // namespace scratchcppgui
Loading