【发布时间】:2017-04-02 19:17:40
【问题描述】:
我正在尝试从图块集中渲染单个图块。比如我想在下面的tileset中显示灰色的tile:
在实际用例中,例如:游戏中的水,草等瓷砖。渲染这些图块有一些要求:
- 它们是 32x32 像素,将全屏呈现,因此性能很重要。
- 缩放时它们不应为 smoothed。
据我所知,没有一个内置的 Qt Quick 类型满足这些要求(渲染未平滑的图像部分)。我试过QQuickPaintedItem 和各种QPainter render hints(比如SmoothPixmapTransform 设置为false)都没有成功;放大时图像“模糊”。 AnimatedSprite 支持渲染图像的部分,但没有禁用平滑的 API。
我的想法是使用场景图 API 实现自定义 QQuickItem。
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickItem>
#include <QQuickWindow>
#include <QSGImageNode>
static QImage image;
static const int tileSize = 32;
static const int tilesetSize = 8;
class Tile : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged)
public:
Tile() :
mIndex(-1) {
setWidth(tileSize);
setHeight(tileSize);
setFlag(QQuickItem::ItemHasContents);
}
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
if (!oldNode) {
oldNode = window()->createImageNode();
}
if (mIndex == -1)
return oldNode;
if (image.isNull()) {
image = QImage("C:/tileset.png");
if (image.isNull())
return oldNode;
}
QSGTexture *texture = window()->createTextureFromImage(image);
qDebug() << "textureSize:" << texture->textureSize();
if (!texture)
return oldNode;
QSGImageNode *imageNode = static_cast<QSGImageNode*>(oldNode);
// imageNode->setOwnsTexture(true);
imageNode->setTexture(texture);
qDebug() << "source rect:" << (mIndex % tileSize) * tileSize << (mIndex / tileSize) * tileSize << tileSize << tileSize;
imageNode->setSourceRect((mIndex % tileSize) * tileSize, (mIndex / tileSize) * tileSize, tileSize, tileSize);
return oldNode;
}
int index() const {
return mIndex;
}
void setIndex(int index) {
if (index == mIndex)
return;
mIndex = index;
emit indexChanged();
}
signals:
void indexChanged();
private:
int mIndex;
};
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<Tile>("App", 1, 0, "Tile");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
#include "main.moc"
main.qml:
import QtQuick 2.9
import QtQuick.Controls 2.2
import App 1.0
ApplicationWindow {
id: window
width: 800
height: 800
visible: true
Slider {
id: slider
from: 1
to: 10
}
Tile {
scale: slider.value
index: 1
anchors.centerIn: parent
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: "darkorange"
}
}
}
此应用程序的输出看起来不错,但矩形内没有呈现任何内容:
textureSize: QSize(256, 256)
source rect: 32 0 32 32
从minimal docs 来看,我的实现(就我如何创建节点而言)似乎还可以。我哪里错了?
【问题讨论】: