Skip to content

Commit 0471c58

Browse files
committed
Add Skin class
1 parent 1adbddb commit 0471c58

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ qt_add_qml_module(scratchcpp-render
3333
irenderedtarget.h
3434
texture.cpp
3535
texture.h
36+
skin.cpp
37+
skin.h
3638
renderedtarget.cpp
3739
renderedtarget.h
3840
targetpainter.cpp

src/skin.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// SPDX-License-Identifier: LGPL-3.0-or-later
2+
3+
#include <scratchcpp/costume.h>
4+
5+
#include "skin.h"
6+
#include "texture.h"
7+
8+
using namespace scratchcpprender;
9+
10+
Skin::Skin(libscratchcpp::Costume *costume)
11+
{
12+
if (!costume)
13+
return;
14+
}
15+
16+
Texture Skin::createAndPaintTexture(int width, int height, bool multisampled)
17+
{
18+
QOpenGLContext *context = QOpenGLContext::currentContext();
19+
20+
if (!context || !context->isValid() || (width <= 0 || height <= 0))
21+
return Texture();
22+
23+
// Create offscreen surface
24+
QOffscreenSurface surface;
25+
surface.setFormat(context->format());
26+
surface.create();
27+
Q_ASSERT(surface.isValid());
28+
29+
// Save old surface
30+
QSurface *oldSurface = context->surface();
31+
32+
// Make context active on the surface
33+
context->makeCurrent(&surface);
34+
35+
const QRectF drawRect(0, 0, width, height);
36+
const QSize drawRectSize = drawRect.size().toSize();
37+
38+
// Create multisampled FBO (if the multisampled parameter is set)
39+
QOpenGLFramebufferObjectFormat format;
40+
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
41+
42+
if (multisampled)
43+
format.setSamples(16);
44+
45+
QOpenGLFramebufferObject fbo(drawRectSize, format);
46+
fbo.bind();
47+
48+
// Create paint device
49+
QOpenGLPaintDevice device(drawRectSize);
50+
QPainter painter(&device);
51+
painter.beginNativePainting();
52+
painter.setRenderHint(QPainter::Antialiasing, false);
53+
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
54+
glClear(GL_COLOR_BUFFER_BIT);
55+
56+
// Call the skin-specific paint method
57+
paint(&painter);
58+
59+
// Done with the painting
60+
painter.endNativePainting();
61+
painter.end();
62+
fbo.release();
63+
64+
GLuint textureHandle;
65+
66+
if (multisampled) {
67+
// Create non-multisampled FBO (we can't take the texture from the multisampled FBO)
68+
format.setSamples(0);
69+
70+
QOpenGLFramebufferObject targetFbo(drawRectSize, format);
71+
targetFbo.bind();
72+
73+
// Blit the multisampled FBO to target FBO
74+
QOpenGLFramebufferObject::blitFramebuffer(&targetFbo, &fbo);
75+
76+
// Take the texture (will call targetFbo.release())
77+
textureHandle = targetFbo.takeTexture();
78+
} else {
79+
// Take the texture
80+
textureHandle = fbo.takeTexture();
81+
}
82+
83+
// Restore old surface
84+
context->doneCurrent();
85+
86+
if (oldSurface)
87+
context->makeCurrent(oldSurface);
88+
89+
return Texture(textureHandle, drawRectSize);
90+
}

src/skin.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: LGPL-3.0-or-later
2+
3+
#pragma once
4+
5+
#include <QPointF>
6+
#include <QSizeF>
7+
#include <QtOpenGL>
8+
9+
namespace libscratchcpp
10+
{
11+
12+
class Costume;
13+
14+
}
15+
16+
namespace scratchcpprender
17+
{
18+
19+
class Texture;
20+
21+
class Skin
22+
{
23+
public:
24+
Skin(libscratchcpp::Costume *costume);
25+
Skin(const Skin &) = delete;
26+
virtual ~Skin() { }
27+
28+
virtual QSizeF size() const = 0;
29+
virtual Texture getTexture(double scale) const = 0;
30+
virtual double getTextureScale(const Texture &texture) const = 0;
31+
32+
protected:
33+
Texture createAndPaintTexture(int width, int height, bool multisampled);
34+
virtual void paint(QPainter *painter) = 0;
35+
};
36+
37+
} // namespace scratchcpprender

0 commit comments

Comments
 (0)