2501 lines · 103.5 KB · C++
RawDownload
    details.vertexSize = FLOATS_PER_VERTEX;     auto verticesBuffer = std::make_shared<gpu::Buffer>();    auto colorBuffer = std::make_shared<gpu::Buffer>();    auto streamFormat = std::make_shared<gpu::Stream::Format>();    auto stream = std::make_shared<gpu::BufferStream>();     details.verticesBuffer = verticesBuffer;    details.colorBuffer = colorBuffer;    details.streamFormat = streamFormat;    details.stream = stream;     details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);    details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);    // TODO: circle3D overlays use this to define their vertices, so they need tex coords    details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));     details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);    details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);     details.vertices = points.size();    details.vertexSize = FLOATS_PER_VERTEX;     float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];    float* vertex = vertexData;     int* colorData = new int[details.vertices];    int* colorDataAt = colorData;     const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);    auto pointCount = points.size();    auto colorCount = colors.size();    int compactColor = 0;    for (auto i = 0; i < pointCount; i++) {        const auto& point = points[i];        *(vertex++) = point.x;        *(vertex++) = point.y;        *(vertex++) = NORMAL.x;        *(vertex++) = NORMAL.y;        *(vertex++) = NORMAL.z;        if (i < colorCount) {            const auto& color = colors[i];            compactColor = ((int(color.x * 255.0f) & 0xFF)) |                ((int(color.y * 255.0f) & 0xFF) << 8) |                ((int(color.z * 255.0f) & 0xFF) << 16) |                ((int(color.w * 255.0f) & 0xFF) << 24);        }        *(colorDataAt++) = compactColor;    }    details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);    details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);    delete[] vertexData;    delete[] colorData; #ifdef WANT_DEBUG    qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size();#endif} void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color) {    updateVertices(id, points, QVector<glm::vec4>({ color }));} void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec4>& colors) {    BatchItemDetails& details = _registeredVertices[id];    if (details.isCreated) {        details.clear();#ifdef WANT_DEBUG        qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED";#endif // def WANT_DEBUG    }     const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals    const int NUM_POS_COORDS = 3;    const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);    details.isCreated = true;    details.vertices = points.size();    details.vertexSize = FLOATS_PER_VERTEX;     auto verticesBuffer = std::make_shared<gpu::Buffer>();    auto colorBuffer = std::make_shared<gpu::Buffer>();    auto streamFormat = std::make_shared<gpu::Stream::Format>();    auto stream = std::make_shared<gpu::BufferStream>();     details.verticesBuffer = verticesBuffer;    details.colorBuffer = colorBuffer;    details.streamFormat = streamFormat;    details.stream = stream;     details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);    details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);    details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));     details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);    details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);     details.vertices = points.size();    details.vertexSize = FLOATS_PER_VERTEX;     // Default to white    int compactColor = 0xFFFFFFFF;    float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];    float* vertex = vertexData;     int* colorData = new int[details.vertices];    int* colorDataAt = colorData;     const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);    auto pointCount = points.size();    auto colorCount = colors.size();    for (auto i = 0; i < pointCount; i++) {        const glm::vec3& point = points[i];        if (i < colorCount) {            const glm::vec4& color = colors[i];            compactColor = ((int(color.x * 255.0f) & 0xFF)) |                ((int(color.y * 255.0f) & 0xFF) << 8) |                ((int(color.z * 255.0f) & 0xFF) << 16) |                ((int(color.w * 255.0f) & 0xFF) << 24);        }        *(vertex++) = point.x;        *(vertex++) = point.y;        *(vertex++) = point.z;        *(vertex++) = NORMAL.x;        *(vertex++) = NORMAL.y;        *(vertex++) = NORMAL.z;        *(colorDataAt++) = compactColor;    }     details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);    details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);    delete[] vertexData;    delete[] colorData; #ifdef WANT_DEBUG    qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size();#endif} void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color) {    updateVertices(id, points, QVector<glm::vec4>({ color }));} void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color) {    BatchItemDetails& details = _registeredVertices[id];     if (details.isCreated) {        details.clear();#ifdef WANT_DEBUG        qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED";#endif // def WANT_DEBUG    }     const int FLOATS_PER_VERTEX = 3 + 3 + 2; // vertices + normals + tex coords    const int NUM_POS_COORDS = 3;    const int NUM_NORMAL_COORDS = 3;    const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);    const int VERTEX_TEX_OFFSET = VERTEX_NORMAL_OFFSET + NUM_NORMAL_COORDS * sizeof(float);    details.isCreated = true;    details.vertices = points.size();    details.vertexSize = FLOATS_PER_VERTEX;     auto verticesBuffer = std::make_shared<gpu::Buffer>();    auto colorBuffer = std::make_shared<gpu::Buffer>();    auto streamFormat = std::make_shared<gpu::Stream::Format>();    auto stream = std::make_shared<gpu::BufferStream>();     details.verticesBuffer = verticesBuffer;    details.colorBuffer = colorBuffer;    details.streamFormat = streamFormat;    details.stream = stream;     details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);    details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);    details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEX_OFFSET);    details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));     details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);    details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);     assert(points.size() == texCoords.size());     details.vertices = points.size();    details.vertexSize = FLOATS_PER_VERTEX;     int compactColor = ((int(color.x * 255.0f) & 0xFF)) |        ((int(color.y * 255.0f) & 0xFF) << 8) |        ((int(color.z * 255.0f) & 0xFF) << 16) |        ((int(color.w * 255.0f) & 0xFF) << 24);     float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];    float* vertex = vertexData;     int* colorData = new int[details.vertices];    int* colorDataAt = colorData;     const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);    for (int i = 0; i < points.size(); i++) {        glm::vec3 point = points[i];        glm::vec2 texCoord = texCoords[i];        *(vertex++) = point.x;        *(vertex++) = point.y;        *(vertex++) = point.z;        *(vertex++) = NORMAL.x;        *(vertex++) = NORMAL.y;        *(vertex++) = NORMAL.z;        *(vertex++) = texCoord.x;        *(vertex++) = texCoord.y;         *(colorDataAt++) = compactColor;    }     details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);    details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);    delete[] vertexData;    delete[] colorData; #ifdef WANT_DEBUG    qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size();#endif} void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id) {    BatchItemDetails& details = _registeredVertices[id];    if (details.isCreated) {        batch.setInputFormat(details.streamFormat);        batch.setInputStream(0, *details.stream);        batch.draw(primitiveType, details.vertices, 0);    }}  void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {    bool registered = (id != UNKNOWN_ID);    Vec3Pair key(glm::vec3(x, y, 0.0f), glm::vec3(width, height, bevelDistance));    BatchItemDetails& details = _registeredBevelRects[id];    // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed    if (registered && details.isCreated) {        Vec3Pair& lastKey = _lastRegisteredBevelRects[id];        if (lastKey != key) {            details.clear();            _lastRegisteredBevelRects[id] = key;#ifdef WANT_DEBUG            qCDebug(renderutils) << "renderBevelCornersRect()... RELEASING REGISTERED";#endif // def WANT_DEBUG        }#ifdef WANT_DEBUG        else {            qCDebug(renderutils) << "renderBevelCornersRect()... REUSING PREVIOUSLY REGISTERED";        }#endif // def WANT_DEBUG    }     if (!details.isCreated) {        static const int FLOATS_PER_VERTEX = 2; // vertices        static const int NUM_VERTICES = 8;        static const int NUM_FLOATS = NUM_VERTICES * FLOATS_PER_VERTEX;         details.isCreated = true;        details.vertices = NUM_VERTICES;        details.vertexSize = FLOATS_PER_VERTEX;         auto verticesBuffer = std::make_shared<gpu::Buffer>();        auto colorBuffer = std::make_shared<gpu::Buffer>();        auto streamFormat = std::make_shared<gpu::Stream::Format>();        auto stream = std::make_shared<gpu::BufferStream>();         details.verticesBuffer = verticesBuffer;        details.colorBuffer = colorBuffer;        details.streamFormat = streamFormat;        details.stream = stream;         details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ));        details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));         details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);        details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);          float vertexBuffer[NUM_FLOATS]; // only vertices, no normals because we're a 2D quad        int vertexPoint = 0;         // Triangle strip points        //      3 ------ 5      //        //    /            \    //        //  1                7  //        //  |                |  //        //  2                8  //        //    \            /    //        //      4 ------ 6      //         // 1        vertexBuffer[vertexPoint++] = x;        vertexBuffer[vertexPoint++] = y + height - bevelDistance;        // 2        vertexBuffer[vertexPoint++] = x;        vertexBuffer[vertexPoint++] = y + bevelDistance;        // 3        vertexBuffer[vertexPoint++] = x + bevelDistance;        vertexBuffer[vertexPoint++] = y + height;        // 4        vertexBuffer[vertexPoint++] = x + bevelDistance;        vertexBuffer[vertexPoint++] = y;        // 5        vertexBuffer[vertexPoint++] = x + width - bevelDistance;        vertexBuffer[vertexPoint++] = y + height;        // 6        vertexBuffer[vertexPoint++] = x + width - bevelDistance;        vertexBuffer[vertexPoint++] = y;        // 7        vertexBuffer[vertexPoint++] = x + width;        vertexBuffer[vertexPoint++] = y + height - bevelDistance;        // 8        vertexBuffer[vertexPoint++] = x + width;        vertexBuffer[vertexPoint++] = y + bevelDistance;         int compactColor = ((int(color.x * 255.0f) & 0xFF)) |            ((int(color.y * 255.0f) & 0xFF) << 8) |            ((int(color.z * 255.0f) & 0xFF) << 16) |            ((int(color.w * 255.0f) & 0xFF) << 24);        int colors[NUM_VERTICES] = { compactColor, compactColor, compactColor, compactColor,            compactColor, compactColor, compactColor, compactColor };          details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer);        details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);    }     batch.setInputFormat(details.streamFormat);    batch.setInputStream(0, *details.stream);    batch.draw(gpu::TRIANGLE_STRIP, details.vertices, 0);} void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id) {    bool registered = (id != UNKNOWN_ID);    Vec4Pair key(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y), color);    BatchItemDetails& details = _registeredQuad2D[id];     // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed    if (registered && details.isCreated) {        Vec4Pair & lastKey = _lastRegisteredQuad2D[id];        if (lastKey != key) {            details.clear();            _lastRegisteredQuad2D[id] = key;#ifdef WANT_DEBUG            qCDebug(renderutils) << "renderQuad() 2D ... RELEASING REGISTERED";#endif // def WANT_DEBUG        }#ifdef WANT_DEBUG        else {            qCDebug(renderutils) << "renderQuad() 2D ... REUSING PREVIOUSLY REGISTERED";        }#endif // def WANT_DEBUG    }     const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals    const int VERTICES = 4; // 1 quad = 4 vertices    const int NUM_POS_COORDS = 2;    const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);     if (!details.isCreated) {         details.isCreated = true;        details.vertices = VERTICES;        details.vertexSize = FLOATS_PER_VERTEX;         auto verticesBuffer = std::make_shared<gpu::Buffer>();        auto colorBuffer = std::make_shared<gpu::Buffer>();        auto streamFormat = std::make_shared<gpu::Stream::Format>();        auto stream = std::make_shared<gpu::BufferStream>();         details.verticesBuffer = verticesBuffer;        details.colorBuffer = colorBuffer;        details.streamFormat = streamFormat;        details.stream = stream;         details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);        details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);        details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));         details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);        details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);          const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);        float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {            minCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z,            maxCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z,            minCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z,            maxCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z,        };         const int NUM_COLOR_SCALARS_PER_QUAD = 4;        int compactColor = ((int(color.x * 255.0f) & 0xFF)) |            ((int(color.y * 255.0f) & 0xFF) << 8) |            ((int(color.z * 255.0f) & 0xFF) << 16) |            ((int(color.w * 255.0f) & 0xFF) << 24);        int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor };         details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer);        details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);    }     batch.setInputFormat(details.streamFormat);    batch.setInputStream(0, *details.stream);    batch.draw(gpu::TRIANGLE_STRIP, 4, 0);} void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id) {    static const glm::vec2 topLeft(-1, 1);    static const glm::vec2 bottomRight(1, -1);    static const glm::vec2 texCoordTopLeft(0.0f, 1.0f);    static const glm::vec2 texCoordBottomRight(1.0f, 0.0f);    renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color, id);} void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,    const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,    const glm::vec4& color, int id) {     Vec4PairVec4 key(Vec4Pair(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y),        glm::vec4(texCoordMinCorner.x, texCoordMinCorner.y, texCoordMaxCorner.x, texCoordMaxCorner.y)),        color);    BatchItemDetails& details = _registeredQuad2DTextures[id];     // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed    if (details.isCreated) {        Vec4PairVec4& lastKey = _lastRegisteredQuad2DTexture[id];        if (lastKey != key) {            details.clear();            _lastRegisteredQuad2DTexture[id] = key;#ifdef WANT_DEBUG            qCDebug(renderutils) << "renderQuad() 2D+texture ... RELEASING REGISTERED";#endif // def WANT_DEBUG        }#ifdef WANT_DEBUG        else {            qCDebug(renderutils) << "renderQuad() 2D+texture ... REUSING PREVIOUSLY REGISTERED";        }#endif // def WANT_DEBUG    }     const int FLOATS_PER_VERTEX = 2 + 3 + 2; // vertices + normals + tex coords    const int VERTICES = 4; // 1 quad = 4 vertices    const int NUM_POS_COORDS = 2;    const int NUM_NORMAL_COORDS = 3;    const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float);    const int VERTEX_TEXCOORD_OFFSET = VERTEX_NORMAL_OFFSET + NUM_NORMAL_COORDS * sizeof(float);     if (!details.isCreated) {         details.isCreated = true;        details.vertices = VERTICES;        details.vertexSize = FLOATS_PER_VERTEX;         auto verticesBuffer = std::make_shared<gpu::Buffer>();        auto colorBuffer = std::make_shared<gpu::Buffer>();         auto streamFormat = std::make_shared<gpu::Stream::Format>();        auto stream = std::make_shared<gpu::BufferStream>();         details.verticesBuffer = verticesBuffer;        details.colorBuffer = colorBuffer;         details.streamFormat = streamFormat;        details.stream = stream;         // zzmp: fix the normal across all renderQuad        details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);        details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET);        details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET);        details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));         details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);        details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);          const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);        float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = {            minCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMinCorner.x, texCoordMinCorner.y,            maxCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMaxCorner.x, texCoordMinCorner.y,            minCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMinCorner.x, texCoordMaxCorner.y,            maxCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMaxCorner.x, texCoordMaxCorner.y,        };          const int NUM_COLOR_SCALARS_PER_QUAD = 4;        int compactColor = ((int(color.x * 255.0f) & 0xFF)) |            ((int(color.y * 255.0f) & 0xFF) << 8) |            ((int(color.z * 255.0f) & 0xFF) << 16) |            ((int(color.w * 255.0f) & 0xFF) << 24);        int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor };         details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer);        details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);    }     batch.setInputFormat(details.streamFormat);    batch.setInputStream(0, *details.stream);    batch.draw(gpu::TRIANGLE_STRIP, 4, 0);}

Lines 1001–1500 of 2501. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t