mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2024-12-02 08:33:00 +08:00
607 lines
19 KiB
C++
607 lines
19 KiB
C++
// Copyright (C) 2022 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
|
|
#include "qrhiimgui_p.h"
|
|
#include <QtCore/qfile.h>
|
|
#include <QtGui/qguiapplication.h>
|
|
#include <QtGui/qevent.h>
|
|
#include <QtGui/qclipboard.h>
|
|
#include <QtGui/qimage.h>
|
|
|
|
#include "imgui.h"
|
|
|
|
// the imgui default
|
|
static_assert(sizeof(ImDrawVert) == 20);
|
|
// switched to uint in imconfig.h to avoid trouble with 4 byte offset alignment reqs
|
|
static_assert(sizeof(ImDrawIdx) == 4);
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
static QShader getShader(const QString &name)
|
|
{
|
|
QFile f(name);
|
|
if (f.open(QIODevice::ReadOnly))
|
|
return QShader::fromSerialized(f.readAll());
|
|
|
|
return QShader();
|
|
}
|
|
|
|
QRhiImguiRenderer::~QRhiImguiRenderer()
|
|
{
|
|
releaseResources();
|
|
}
|
|
|
|
void QRhiImguiRenderer::releaseResources()
|
|
{
|
|
for (Texture &t : m_textures) {
|
|
delete t.tex;
|
|
delete t.srb;
|
|
}
|
|
m_textures.clear();
|
|
|
|
m_vbuf.reset();
|
|
m_ibuf.reset();
|
|
m_ubuf.reset();
|
|
m_ps.reset();
|
|
m_sampler.reset();
|
|
|
|
m_rhi = nullptr;
|
|
}
|
|
|
|
void QRhiImguiRenderer::prepare(QRhi *rhi, QRhiRenderTarget *rt, QRhiCommandBuffer *cb, const QMatrix4x4 &mvp, float opacity)
|
|
{
|
|
if (!m_rhi) {
|
|
m_rhi = rhi;
|
|
} else if (m_rhi != rhi) {
|
|
releaseResources();
|
|
m_rhi = rhi;
|
|
}
|
|
|
|
if (!m_rhi || f.draw.isEmpty())
|
|
return;
|
|
|
|
m_rt = rt;
|
|
m_cb = cb;
|
|
|
|
if (!m_vbuf) {
|
|
m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, f.totalVbufSize));
|
|
m_vbuf->setName(QByteArrayLiteral("imgui vertex buffer"));
|
|
if (!m_vbuf->create())
|
|
return;
|
|
} else {
|
|
if (f.totalVbufSize > m_vbuf->size()) {
|
|
m_vbuf->setSize(f.totalVbufSize);
|
|
if (!m_vbuf->create())
|
|
return;
|
|
}
|
|
}
|
|
if (!m_ibuf) {
|
|
m_ibuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::IndexBuffer, f.totalIbufSize));
|
|
m_ibuf->setName(QByteArrayLiteral("imgui index buffer"));
|
|
if (!m_ibuf->create())
|
|
return;
|
|
} else {
|
|
if (f.totalIbufSize > m_ibuf->size()) {
|
|
m_ibuf->setSize(f.totalIbufSize);
|
|
if (!m_ibuf->create())
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!m_ubuf) {
|
|
m_ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4));
|
|
m_ubuf->setName(QByteArrayLiteral("imgui uniform buffer"));
|
|
if (!m_ubuf->create())
|
|
return;
|
|
}
|
|
|
|
if (!m_sampler) {
|
|
m_sampler.reset(m_rhi->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
|
|
QRhiSampler::Repeat, QRhiSampler::Repeat));
|
|
m_sampler->setName(QByteArrayLiteral("imgui sampler"));
|
|
if (!m_sampler->create())
|
|
return;
|
|
}
|
|
|
|
if (m_textures.isEmpty()) {
|
|
Texture fontTex;
|
|
fontTex.image = sf.fontTextureData;
|
|
m_textures.append(fontTex);
|
|
} else if (!sf.fontTextureData.isNull()) {
|
|
Texture fontTex;
|
|
fontTex.image = sf.fontTextureData;
|
|
delete m_textures[0].tex;
|
|
delete m_textures[0].srb;
|
|
m_textures[0] = fontTex;
|
|
}
|
|
|
|
QVarLengthArray<int, 8> texturesNeedUpdate;
|
|
for (int i = 0; i < m_textures.count(); ++i) {
|
|
Texture &t(m_textures[i]);
|
|
if (!t.tex) {
|
|
t.tex = m_rhi->newTexture(QRhiTexture::RGBA8, t.image.size());
|
|
t.tex->setName(QByteArrayLiteral("imgui texture ") + QByteArray::number(i));
|
|
if (!t.tex->create())
|
|
return;
|
|
texturesNeedUpdate.append(i);
|
|
}
|
|
if (!t.srb) {
|
|
t.srb = m_rhi->newShaderResourceBindings();
|
|
t.srb->setBindings({
|
|
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf.get()),
|
|
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, t.tex, m_sampler.get())
|
|
});
|
|
if (!t.srb->create())
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If layer.enabled is toggled on the item or an ancestor, the render
|
|
// target is then suddenly different and may not be compatible.
|
|
if (m_ps && m_rt->renderPassDescriptor()->serializedFormat() != m_renderPassFormat)
|
|
m_ps.reset();
|
|
|
|
if (!m_ps) {
|
|
QShader vs = getShader(QLatin1String(":/imgui.vert.qsb"));
|
|
QShader fs = getShader(QLatin1String(":/imgui.frag.qsb"));
|
|
if (!vs.isValid() || !fs.isValid()) {
|
|
qWarning("Failed to load imgui shaders");
|
|
return;
|
|
}
|
|
|
|
m_ps.reset(m_rhi->newGraphicsPipeline());
|
|
QRhiGraphicsPipeline::TargetBlend blend;
|
|
blend.enable = true;
|
|
// Premultiplied alpha (matches imgui.frag). Would not be needed if we
|
|
// only cared about outputting to the window (the common case), but
|
|
// once going through a texture (Item layer, ShaderEffect) which is
|
|
// then sampled by Quick, the result wouldn't be correct otherwise.
|
|
blend.srcColor = QRhiGraphicsPipeline::One;
|
|
blend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
|
|
blend.srcAlpha = QRhiGraphicsPipeline::One;
|
|
blend.dstAlpha = QRhiGraphicsPipeline::OneMinusSrcAlpha;
|
|
m_ps->setTargetBlends({ blend });
|
|
m_ps->setCullMode(QRhiGraphicsPipeline::None);
|
|
m_ps->setDepthTest(true);
|
|
m_ps->setDepthOp(QRhiGraphicsPipeline::LessOrEqual);
|
|
m_ps->setDepthWrite(false);
|
|
m_ps->setFlags(QRhiGraphicsPipeline::UsesScissor);
|
|
|
|
m_ps->setShaderStages({
|
|
{ QRhiShaderStage::Vertex, vs },
|
|
{ QRhiShaderStage::Fragment, fs }
|
|
});
|
|
|
|
QRhiVertexInputLayout inputLayout;
|
|
inputLayout.setBindings({
|
|
{ 4 * sizeof(float) + sizeof(quint32) }
|
|
});
|
|
inputLayout.setAttributes({
|
|
{ 0, 0, QRhiVertexInputAttribute::Float2, 0 },
|
|
{ 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) },
|
|
{ 0, 2, QRhiVertexInputAttribute::UNormByte4, 4 * sizeof(float) }
|
|
});
|
|
|
|
m_ps->setVertexInputLayout(inputLayout);
|
|
m_ps->setShaderResourceBindings(m_textures[0].srb);
|
|
m_ps->setRenderPassDescriptor(m_rt->renderPassDescriptor());
|
|
m_renderPassFormat = m_rt->renderPassDescriptor()->serializedFormat();
|
|
|
|
if (!m_ps->create())
|
|
return;
|
|
}
|
|
|
|
QRhiResourceUpdateBatch *u = m_rhi->nextResourceUpdateBatch();
|
|
|
|
for (const CmdListBuffer &b : f.vbuf)
|
|
u->updateDynamicBuffer(m_vbuf.get(), b.offset, b.data.size(), b.data.constData());
|
|
|
|
for (const CmdListBuffer &b : f.ibuf)
|
|
u->updateDynamicBuffer(m_ibuf.get(), b.offset, b.data.size(), b.data.constData());
|
|
|
|
u->updateDynamicBuffer(m_ubuf.get(), 0, 64, mvp.constData());
|
|
u->updateDynamicBuffer(m_ubuf.get(), 64, 4, &opacity);
|
|
|
|
for (int i = 0; i < texturesNeedUpdate.count(); ++i) {
|
|
Texture &t(m_textures[texturesNeedUpdate[i]]);
|
|
u->uploadTexture(t.tex, t.image);
|
|
t.image = QImage();
|
|
}
|
|
|
|
m_cb->resourceUpdate(u);
|
|
}
|
|
|
|
void QRhiImguiRenderer::render()
|
|
{
|
|
if (!m_rhi || f.draw.isEmpty() || !m_ps)
|
|
return;
|
|
|
|
m_cb->setGraphicsPipeline(m_ps.get());
|
|
|
|
const QSize viewportSize = m_rt->pixelSize();
|
|
bool needsViewport = true;
|
|
|
|
for (const DrawCmd &c : f.draw) {
|
|
QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), f.vbuf[c.cmdListBufferIdx].offset);
|
|
if (needsViewport) {
|
|
needsViewport = false;
|
|
m_cb->setViewport({ 0, 0, float(viewportSize.width()), float(viewportSize.height()) });
|
|
}
|
|
const float sx1 = c.clipRect.x() + c.itemPixelOffset.x();
|
|
const float sy1 = c.clipRect.y() + c.itemPixelOffset.y();
|
|
const float sx2 = c.clipRect.z() + c.itemPixelOffset.x();
|
|
const float sy2 = c.clipRect.w() + c.itemPixelOffset.y();
|
|
QPoint scissorPos = QPointF(sx1, viewportSize.height() - sy2).toPoint();
|
|
QSize scissorSize = QSizeF(sx2 - sx1, sy2 - sy1).toSize();
|
|
scissorPos.setX(qMax(0, scissorPos.x()));
|
|
scissorPos.setY(qMax(0, scissorPos.y()));
|
|
scissorSize.setWidth(qMin(viewportSize.width(), scissorSize.width()));
|
|
scissorSize.setHeight(qMin(viewportSize.height(), scissorSize.height()));
|
|
m_cb->setScissor({ scissorPos.x(), scissorPos.y(), scissorSize.width(), scissorSize.height() });
|
|
m_cb->setShaderResources(m_textures[c.textureIndex].srb);
|
|
m_cb->setVertexInput(0, 1, &vbufBinding, m_ibuf.get(), c.indexOffset, QRhiCommandBuffer::IndexUInt32);
|
|
m_cb->drawIndexed(c.elemCount);
|
|
}
|
|
}
|
|
|
|
static const char *getClipboardText(void *)
|
|
{
|
|
static QByteArray contents;
|
|
contents = QGuiApplication::clipboard()->text().toUtf8();
|
|
return contents.constData();
|
|
}
|
|
|
|
static void setClipboardText(void *, const char *text)
|
|
{
|
|
QGuiApplication::clipboard()->setText(QString::fromUtf8(text));
|
|
}
|
|
|
|
QRhiImgui::QRhiImgui()
|
|
{
|
|
ImGui::CreateContext();
|
|
rebuildFontAtlas();
|
|
ImGuiIO &io(ImGui::GetIO());
|
|
io.GetClipboardTextFn = getClipboardText;
|
|
io.SetClipboardTextFn = setClipboardText;
|
|
}
|
|
|
|
QRhiImgui::~QRhiImgui()
|
|
{
|
|
ImGui::DestroyContext();
|
|
}
|
|
|
|
void QRhiImgui::rebuildFontAtlas()
|
|
{
|
|
unsigned char *pixels;
|
|
int w, h;
|
|
ImGuiIO &io(ImGui::GetIO());
|
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &w, &h);
|
|
const QImage wrapperImg(const_cast<const uchar *>(pixels), w, h, QImage::Format_RGBA8888);
|
|
sf.fontTextureData = wrapperImg.copy();
|
|
io.Fonts->SetTexID(reinterpret_cast<ImTextureID>(quintptr(0)));
|
|
}
|
|
|
|
void QRhiImgui::nextFrame(const QSizeF &logicalOutputSize, float dpr, const QPointF &logicalOffset, FrameFunc frameFunc)
|
|
{
|
|
ImGuiIO &io(ImGui::GetIO());
|
|
|
|
const QPointF itemPixelOffset = logicalOffset * dpr;
|
|
f.outputPixelSize = (logicalOutputSize * dpr).toSize();
|
|
io.DisplaySize.x = logicalOutputSize.width();
|
|
io.DisplaySize.y = logicalOutputSize.height();
|
|
io.DisplayFramebufferScale = ImVec2(dpr, dpr);
|
|
|
|
ImGui::NewFrame();
|
|
if (frameFunc)
|
|
frameFunc();
|
|
ImGui::Render();
|
|
|
|
ImDrawData *draw = ImGui::GetDrawData();
|
|
draw->ScaleClipRects(ImVec2(dpr, dpr));
|
|
|
|
f.vbuf.resize(draw->CmdListsCount);
|
|
f.ibuf.resize(draw->CmdListsCount);
|
|
f.totalVbufSize = 0;
|
|
f.totalIbufSize = 0;
|
|
for (int n = 0; n < draw->CmdListsCount; ++n) {
|
|
const ImDrawList *cmdList = draw->CmdLists[n];
|
|
const int vbufSize = cmdList->VtxBuffer.Size * sizeof(ImDrawVert);
|
|
f.vbuf[n].offset = f.totalVbufSize;
|
|
f.totalVbufSize += vbufSize;
|
|
const int ibufSize = cmdList->IdxBuffer.Size * sizeof(ImDrawIdx);
|
|
f.ibuf[n].offset = f.totalIbufSize;
|
|
f.totalIbufSize += ibufSize;
|
|
}
|
|
f.draw.clear();
|
|
for (int n = 0; n < draw->CmdListsCount; ++n) {
|
|
const ImDrawList *cmdList = draw->CmdLists[n];
|
|
f.vbuf[n].data = QByteArray(reinterpret_cast<const char *>(cmdList->VtxBuffer.Data),
|
|
cmdList->VtxBuffer.Size * sizeof(ImDrawVert));
|
|
f.ibuf[n].data = QByteArray(reinterpret_cast<const char *>(cmdList->IdxBuffer.Data),
|
|
cmdList->IdxBuffer.Size * sizeof(ImDrawIdx));
|
|
const ImDrawIdx *indexBufOffset = nullptr;
|
|
for (int i = 0; i < cmdList->CmdBuffer.Size; ++i) {
|
|
const ImDrawCmd *cmd = &cmdList->CmdBuffer[i];
|
|
const quint32 indexOffset = f.ibuf[n].offset + quintptr(indexBufOffset);
|
|
if (!cmd->UserCallback) {
|
|
QRhiImguiRenderer::DrawCmd dc;
|
|
dc.cmdListBufferIdx = n;
|
|
dc.textureIndex = int(reinterpret_cast<qintptr>(cmd->TextureId));
|
|
dc.indexOffset = indexOffset;
|
|
dc.elemCount = cmd->ElemCount;
|
|
dc.itemPixelOffset = itemPixelOffset;
|
|
dc.clipRect = QVector4D(cmd->ClipRect.x, cmd->ClipRect.y, cmd->ClipRect.z, cmd->ClipRect.w);
|
|
f.draw.append(dc);
|
|
} else {
|
|
cmd->UserCallback(cmdList, cmd);
|
|
}
|
|
indexBufOffset += cmd->ElemCount;
|
|
}
|
|
}
|
|
}
|
|
|
|
void QRhiImgui::syncRenderer(QRhiImguiRenderer *renderer)
|
|
{
|
|
renderer->sf = sf;
|
|
sf.fontTextureData = QImage();
|
|
renderer->f = std::move(f);
|
|
}
|
|
|
|
static void updateKeyboardModifiers(Qt::KeyboardModifiers modifiers)
|
|
{
|
|
ImGuiIO &io(ImGui::GetIO());
|
|
io.AddKeyEvent(ImGuiKey_ModCtrl, modifiers.testFlag(Qt::ControlModifier));
|
|
io.AddKeyEvent(ImGuiKey_ModShift, modifiers.testFlag(Qt::ShiftModifier));
|
|
io.AddKeyEvent(ImGuiKey_ModAlt, modifiers.testFlag(Qt::AltModifier));
|
|
io.AddKeyEvent(ImGuiKey_ModSuper, modifiers.testFlag(Qt::MetaModifier));
|
|
}
|
|
|
|
static ImGuiKey mapKey(int k)
|
|
{
|
|
switch (k) {
|
|
case Qt::Key_Space:
|
|
return ImGuiKey_Space;
|
|
case Qt::Key_Apostrophe:
|
|
return ImGuiKey_Apostrophe;
|
|
case Qt::Key_Comma:
|
|
return ImGuiKey_Comma;
|
|
case Qt::Key_Minus:
|
|
return ImGuiKey_Minus;
|
|
case Qt::Key_Period:
|
|
return ImGuiKey_Period;
|
|
case Qt::Key_Slash:
|
|
return ImGuiKey_Slash;
|
|
case Qt::Key_0:
|
|
return ImGuiKey_0;
|
|
case Qt::Key_1:
|
|
return ImGuiKey_1;
|
|
case Qt::Key_2:
|
|
return ImGuiKey_2;
|
|
case Qt::Key_3:
|
|
return ImGuiKey_3;
|
|
case Qt::Key_4:
|
|
return ImGuiKey_4;
|
|
case Qt::Key_5:
|
|
return ImGuiKey_5;
|
|
case Qt::Key_6:
|
|
return ImGuiKey_6;
|
|
case Qt::Key_7:
|
|
return ImGuiKey_8;
|
|
case Qt::Key_8:
|
|
return ImGuiKey_8;
|
|
case Qt::Key_9:
|
|
return ImGuiKey_9;
|
|
case Qt::Key_Semicolon:
|
|
return ImGuiKey_Semicolon;
|
|
case Qt::Key_Equal:
|
|
return ImGuiKey_Equal;
|
|
case Qt::Key_A:
|
|
return ImGuiKey_A;
|
|
case Qt::Key_B:
|
|
return ImGuiKey_B;
|
|
case Qt::Key_C:
|
|
return ImGuiKey_C;
|
|
case Qt::Key_D:
|
|
return ImGuiKey_D;
|
|
case Qt::Key_E:
|
|
return ImGuiKey_E;
|
|
case Qt::Key_F:
|
|
return ImGuiKey_F;
|
|
case Qt::Key_G:
|
|
return ImGuiKey_G;
|
|
case Qt::Key_H:
|
|
return ImGuiKey_H;
|
|
case Qt::Key_I:
|
|
return ImGuiKey_I;
|
|
case Qt::Key_J:
|
|
return ImGuiKey_J;
|
|
case Qt::Key_K:
|
|
return ImGuiKey_K;
|
|
case Qt::Key_L:
|
|
return ImGuiKey_L;
|
|
case Qt::Key_M:
|
|
return ImGuiKey_M;
|
|
case Qt::Key_N:
|
|
return ImGuiKey_N;
|
|
case Qt::Key_O:
|
|
return ImGuiKey_O;
|
|
case Qt::Key_P:
|
|
return ImGuiKey_P;
|
|
case Qt::Key_Q:
|
|
return ImGuiKey_Q;
|
|
case Qt::Key_R:
|
|
return ImGuiKey_R;
|
|
case Qt::Key_S:
|
|
return ImGuiKey_S;
|
|
case Qt::Key_T:
|
|
return ImGuiKey_T;
|
|
case Qt::Key_U:
|
|
return ImGuiKey_U;
|
|
case Qt::Key_V:
|
|
return ImGuiKey_V;
|
|
case Qt::Key_W:
|
|
return ImGuiKey_W;
|
|
case Qt::Key_X:
|
|
return ImGuiKey_X;
|
|
case Qt::Key_Y:
|
|
return ImGuiKey_Y;
|
|
case Qt::Key_Z:
|
|
return ImGuiKey_Z;
|
|
case Qt::Key_BracketLeft:
|
|
return ImGuiKey_LeftBracket;
|
|
case Qt::Key_Backslash:
|
|
return ImGuiKey_Backslash;
|
|
case Qt::Key_BracketRight:
|
|
return ImGuiKey_RightBracket;
|
|
case Qt::Key_QuoteLeft:
|
|
return ImGuiKey_GraveAccent;
|
|
case Qt::Key_Escape:
|
|
return ImGuiKey_Escape;
|
|
case Qt::Key_Tab:
|
|
return ImGuiKey_Tab;
|
|
case Qt::Key_Backspace:
|
|
return ImGuiKey_Backspace;
|
|
case Qt::Key_Return:
|
|
case Qt::Key_Enter:
|
|
return ImGuiKey_Enter;
|
|
case Qt::Key_Insert:
|
|
return ImGuiKey_Insert;
|
|
case Qt::Key_Delete:
|
|
return ImGuiKey_Delete;
|
|
case Qt::Key_Pause:
|
|
return ImGuiKey_Pause;
|
|
case Qt::Key_Print:
|
|
return ImGuiKey_PrintScreen;
|
|
case Qt::Key_Home:
|
|
return ImGuiKey_Home;
|
|
case Qt::Key_End:
|
|
return ImGuiKey_End;
|
|
case Qt::Key_Left:
|
|
return ImGuiKey_LeftArrow;
|
|
case Qt::Key_Up:
|
|
return ImGuiKey_UpArrow;
|
|
case Qt::Key_Right:
|
|
return ImGuiKey_RightArrow;
|
|
case Qt::Key_Down:
|
|
return ImGuiKey_DownArrow;
|
|
case Qt::Key_PageUp:
|
|
return ImGuiKey_PageUp;
|
|
case Qt::Key_PageDown:
|
|
return ImGuiKey_PageDown;
|
|
case Qt::Key_Shift:
|
|
return ImGuiKey_LeftShift;
|
|
case Qt::Key_Control:
|
|
return ImGuiKey_LeftCtrl;
|
|
case Qt::Key_Meta:
|
|
return ImGuiKey_LeftSuper;
|
|
case Qt::Key_Alt:
|
|
return ImGuiKey_LeftAlt;
|
|
case Qt::Key_CapsLock:
|
|
return ImGuiKey_CapsLock;
|
|
case Qt::Key_NumLock:
|
|
return ImGuiKey_NumLock;
|
|
case Qt::Key_ScrollLock:
|
|
return ImGuiKey_ScrollLock;
|
|
case Qt::Key_F1:
|
|
return ImGuiKey_F1;
|
|
case Qt::Key_F2:
|
|
return ImGuiKey_F2;
|
|
case Qt::Key_F3:
|
|
return ImGuiKey_F3;
|
|
case Qt::Key_F4:
|
|
return ImGuiKey_F4;
|
|
case Qt::Key_F5:
|
|
return ImGuiKey_F5;
|
|
case Qt::Key_F6:
|
|
return ImGuiKey_F6;
|
|
case Qt::Key_F7:
|
|
return ImGuiKey_F7;
|
|
case Qt::Key_F8:
|
|
return ImGuiKey_F8;
|
|
case Qt::Key_F9:
|
|
return ImGuiKey_F9;
|
|
case Qt::Key_F10:
|
|
return ImGuiKey_F10;
|
|
case Qt::Key_F11:
|
|
return ImGuiKey_F11;
|
|
case Qt::Key_F12:
|
|
return ImGuiKey_F12;
|
|
default:
|
|
break;
|
|
}
|
|
return ImGuiKey_None;
|
|
}
|
|
|
|
bool QRhiImgui::processEvent(QEvent *event)
|
|
{
|
|
ImGuiIO &io(ImGui::GetIO());
|
|
|
|
switch (event->type()) {
|
|
case QEvent::MouseButtonPress:
|
|
{
|
|
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
|
updateKeyboardModifiers(me->modifiers());
|
|
Qt::MouseButtons buttons = me->buttons();
|
|
if (buttons.testFlag(Qt::LeftButton) && !pressedMouseButtons.testFlag(Qt::LeftButton))
|
|
io.AddMouseButtonEvent(0, true);
|
|
if (buttons.testFlag(Qt::RightButton) && !pressedMouseButtons.testFlag(Qt::RightButton))
|
|
io.AddMouseButtonEvent(1, true);
|
|
if (buttons.testFlag(Qt::MiddleButton) && !pressedMouseButtons.testFlag(Qt::MiddleButton))
|
|
io.AddMouseButtonEvent(2, true);
|
|
pressedMouseButtons = buttons;
|
|
}
|
|
return true;
|
|
|
|
case QEvent::MouseButtonRelease:
|
|
{
|
|
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
|
Qt::MouseButtons buttons = me->buttons();
|
|
if (!buttons.testFlag(Qt::LeftButton) && pressedMouseButtons.testFlag(Qt::LeftButton))
|
|
io.AddMouseButtonEvent(0, false);
|
|
if (!buttons.testFlag(Qt::RightButton) && pressedMouseButtons.testFlag(Qt::RightButton))
|
|
io.AddMouseButtonEvent(1, false);
|
|
if (!buttons.testFlag(Qt::MiddleButton) && pressedMouseButtons.testFlag(Qt::MiddleButton))
|
|
io.AddMouseButtonEvent(2, false);
|
|
pressedMouseButtons = buttons;
|
|
}
|
|
return true;
|
|
|
|
case QEvent::MouseMove:
|
|
{
|
|
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
|
const QPointF pos = me->position();
|
|
io.AddMousePosEvent(pos.x(), pos.y());
|
|
}
|
|
return true;
|
|
|
|
case QEvent::Wheel:
|
|
{
|
|
QWheelEvent *we = static_cast<QWheelEvent *>(event);
|
|
QPointF wheel(we->angleDelta().x() / 120.0f, we->angleDelta().y() / 120.0f);
|
|
io.AddMouseWheelEvent(wheel.x(), wheel.y());
|
|
}
|
|
return true;
|
|
|
|
case QEvent::KeyPress:
|
|
case QEvent::KeyRelease:
|
|
{
|
|
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
|
const bool down = event->type() == QEvent::KeyPress;
|
|
updateKeyboardModifiers(ke->modifiers());
|
|
io.AddKeyEvent(mapKey(ke->key()), down);
|
|
if (down && !ke->text().isEmpty()) {
|
|
const QByteArray text = ke->text().toUtf8();
|
|
io.AddInputCharactersUTF8(text.constData());
|
|
}
|
|
}
|
|
return true;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
QT_END_NAMESPACE
|