-
Notifications
You must be signed in to change notification settings - Fork 530
[Sensor] Fisheye Sensor #1131
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
[Sensor] Fisheye Sensor #1131
Changes from all commits
Commits
Show all changes
150 commits
Select commit
Hold shift + click to select a range
9532699
CubeMap
bigbike 30ef2e8
minor
bigbike da000af
TODO: color map only
bigbike 89164c2
minor
bigbike c66c689
minor
bigbike d4d149e
Merge branch 'master' into cubemap
bigbike 1339614
minor
bigbike b3309fa
minor
bigbike 21f2cba
debugging using viewer
bigbike c85b2f2
minor
bigbike 21f2c3e
minor
bigbike 19d78a1
Merge branch 'master' into cubemap
bigbike 6a7eb5a
minor
bigbike c4f17f1
Merge branch 'master' into cubemap
bigbike 9d100a2
minor
bigbike f82a6b2
minor
bigbike cc9fdcc
debugging
bigbike 1a10490
debugging the shader_->draw(mesh_);
bigbike b1e6f2c
debugging the fisheye sensor
bigbike 0cf87dd
minor, debugging
bigbike f45b8ed
minor
bigbike c816b41
Merge branch 'master' into cubemap
bigbike 6e7159a
minor debugging - can see fisheye effect
bigbike 444c9aa
debugging, the seam on the boundary
bigbike 8daa818
fisheyesensor is working now. missing generateMipmap before
bigbike 1b75d9a
minor
bigbike 991e5c1
minor
bigbike 7d8202d
Merge branch 'master' into cubemap
bigbike 2a3059b
minor
bigbike 109d7de
minor
bigbike 489b236
minor
bigbike eea98fd
minor
bigbike 7839189
Merge branch 'master' into cubemap
bigbike 5b7afd4
webgl
bigbike 0cf748e
Merge branch 'master' into cubemap
bigbike 6183e9a
minor
bigbike 4a55f0c
address reviwer's concerns
bigbike 2934036
Merge branch 'master' into cubemap
bigbike e855b90
Merge branch 'master' into cubemap
bigbike 06af285
minor
bigbike 5ab1893
Merge branch 'master' into cubemap
bigbike fbeeb19
minor
bigbike c334225
minor
bigbike 93199c2
minor
bigbike da62eb7
Merge branch 'master' into cubemap
bigbike 1c6eeeb
add visualization of depth sensor
bigbike 2837700
minor
bigbike 0b8d7d4
Merge branch 'master' into cubemap
bigbike 6c5de10
minor
bigbike b4d0e61
debug cubemap save/load textures for depth texture
bigbike a68ad92
debugging
bigbike 4a827eb
Merge branch 'master' into cubemap
bigbike 1c67be9
Merge branch 'master' into cubemap
bigbike d26c1b9
6 fbo
bigbike 4e5d403
fix bug
bigbike a069ce1
minor
bigbike 4f674bd
Merge branch 'cubemap-6fbo' into cubemap
bigbike 876e724
minor
bigbike 4070bc4
Merge branch 'cubemap-6fbo' into cubemap
bigbike d217836
minor
bigbike 5f8f3d4
Merge branch 'master' into cubemap
bigbike b64ff78
minor
bigbike 3a2f21b
debugging save / load
bigbike 8fa38dd
clean up
bigbike 22f72ad
Merge branch 'master' into cubemap
bigbike c64326f
debug
bigbike bf4ca18
minor
bigbike 6ea8733
minor
bigbike 0dcb6fb
minor
bigbike d65d416
Merge branch 'master' into cubemap
bigbike 93108e0
Merge branch 'master' into cubemap
bigbike 7394424
Merge branch 'master' into cubemap
bigbike 0b8f43e
Merge branch 'master' into cubemap
bigbike ba25971
minor
bigbike 0da71f2
optimization
bigbike 2ec2b9e
minor
bigbike 0ffa5ab
minor
bigbike 310492c
js
bigbike 72cc970
minor
bigbike b52c6c5
minor
bigbike 1ece0f2
minor
bigbike ab101b6
minor
bigbike 2cb5c4d
minor
bigbike addb0dc
minor
bigbike 5a23651
minor
bigbike d7c3d17
minor
bigbike d35b804
fix fetal bugs when viewpoprt changes
bigbike 1204a8b
Merge branch 'master' into cubemap
bigbike a57ba8c
minor
bigbike 5030cbd
minor
bigbike baf518e
Merge branch 'master' into cubemap
bigbike 4284864
minor
bigbike c7357f6
minor
bigbike 2f3f51a
minor
bigbike 4b98a03
minor
bigbike 958fa1a
minor
bigbike ef4c649
fix fetal bugs when viewpoprt changes
bigbike 74b042b
minor
bigbike 04758fd
Merge branch 'cubemap-pr' of github.com:facebookresearch/habitat-sim …
bigbike 2562e4d
minor
bigbike a20cdc2
minor
bigbike e50e296
Merge branch 'master' into cubemap
bigbike a895fd5
minor
bigbike f564f9a
minor
bigbike 21738ce
minor
bigbike 0b10063
minor
bigbike 4a9da9d
minor
bigbike bda08b6
minor
bigbike e394a95
fix fetal bugs when viewpoprt changes
bigbike 9112601
minor
bigbike 6c086e6
minor
bigbike e634995
minor
bigbike 78ff9e2
fix fetal bugs when viewpoprt changes
bigbike 7e13726
Merge branch 'cubemap-pr' of github.com:facebookresearch/habitat-sim …
bigbike 4208e8a
minor
bigbike 8f464c6
minor
bigbike ae5e648
minor
bigbike 042f56a
minor
bigbike ea47949
minor
bigbike 2ee6138
minor
bigbike fae1fb4
minor
bigbike 74beb1a
Merge branch 'master' into cubemap
bigbike c8eab7e
fix shader to make it compatible with webGL
bigbike 6717b79
Merge branch 'master' into cubemap
bigbike 4a0cd6d
minor
bigbike 4bb8367
minor
bigbike f19eaf6
minor
bigbike a9c8115
minor
bigbike 2c03d72
fix fetal bugs when viewpoprt changes
bigbike 43e9cb5
minor
bigbike 8cd7ae4
fix fetal bugs when viewpoprt changes
bigbike d85b57c
minor
bigbike da0d6a7
minor
bigbike bd192b8
minor
bigbike ba7359e
minor
bigbike 985321d
fix fetal bugs when viewpoprt changes
bigbike 5dba29e
minor
bigbike a4291d7
minor
bigbike c5496b0
minor
bigbike 7553788
minor
bigbike 730baf9
minor
bigbike 598fbde
fix fetal bugs when viewpoprt changes
bigbike 184129c
minor
bigbike ebda3aa
minor
bigbike ae45d58
minor
bigbike aaefb0c
minor
bigbike 4d0fd0b
minor
bigbike dd9b27c
minor
bigbike d04d164
minor
bigbike 1689cbc
Merge branch 'cubemap-pr' of github.com:facebookresearch/habitat-sim …
bigbike File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| // Copyright (c) Facebook, Inc. and its affiliates. | ||
| // This source code is licensed under the MIT license found in the | ||
| // LICENSE file in the root directory of this source tree. | ||
| #include "DoubleSphereCameraShader.h" | ||
|
|
||
| #include <Corrade/Containers/Reference.h> | ||
| #include <Corrade/Utility/Assert.h> | ||
| #include <Corrade/Utility/FormatStl.h> | ||
| #include <Corrade/Utility/Resource.h> | ||
| #include <Magnum/GL/Shader.h> | ||
| #include <Magnum/GL/Texture.h> | ||
| #include <Magnum/GL/Version.h> | ||
|
|
||
| #include <sstream> | ||
|
|
||
| // This is to import the "resources" at runtime. When the resource is | ||
| // compiled into static library, it must be explicitly initialized via this | ||
| // macro, and should be called *outside* of any namespace. | ||
| static void importShaderResources() { | ||
| CORRADE_RESOURCE_INITIALIZE(ShaderResources) | ||
| } | ||
|
|
||
| namespace Mn = Magnum; | ||
| namespace Cr = Corrade; | ||
|
|
||
| namespace esp { | ||
| namespace gfx { | ||
| DoubleSphereCameraShader::DoubleSphereCameraShader(FisheyeShader::Flags flags) | ||
| : FisheyeShader(flags) { | ||
| if (!Cr::Utility::Resource::hasGroup("default-shaders")) { | ||
| importShaderResources(); | ||
| } | ||
|
|
||
| #ifdef MAGNUM_TARGET_WEBGL | ||
| Mn::GL::Version glVersion = Mn::GL::Version::GLES300; | ||
| #else | ||
| Mn::GL::Version glVersion = Mn::GL::Version::GL410; | ||
| #endif | ||
|
|
||
| // this is not the file name, but the group name in the config file | ||
| // see Shaders.conf in the shaders folder | ||
| const Cr::Utility::Resource rs{"default-shaders"}; | ||
|
|
||
| Mn::GL::Shader vert{glVersion, Mn::GL::Shader::Type::Vertex}; | ||
| Mn::GL::Shader frag{glVersion, Mn::GL::Shader::Type::Fragment}; | ||
|
|
||
| // Add macros | ||
| vert.addSource(rs.get("bigTriangle.vert")); | ||
|
|
||
| std::stringstream outputAttributeLocationsStream; | ||
|
|
||
| if (flags_ & FisheyeShader::Flag::ColorTexture) { | ||
| outputAttributeLocationsStream << Cr::Utility::formatString( | ||
| "#define OUTPUT_ATTRIBUTE_LOCATION_COLOR {}\n", ColorOutput); | ||
| } | ||
| /* TODO: | ||
| outputAttributeLocationsStream << Cr::Utility::formatString( | ||
| "#define OUTPUT_ATTRIBUTE_LOCATION_OBJECT_ID {}\n", ObjectIdOutput); | ||
| */ | ||
|
|
||
| frag.addSource(outputAttributeLocationsStream.str()) | ||
| .addSource(flags_ & FisheyeShader::Flag::ColorTexture | ||
| ? "#define COLOR_TEXTURE\n" | ||
| : "") | ||
| .addSource(flags_ & FisheyeShader::Flag::DepthTexture | ||
| ? "#define DEPTH_TEXTURE\n" | ||
| : "") | ||
| .addSource(rs.get("doubleSphereCamera.frag")); | ||
|
|
||
| CORRADE_INTERNAL_ASSERT_OUTPUT(Mn::GL::Shader::compile({vert, frag})); | ||
|
|
||
| attachShaders({vert, frag}); | ||
|
|
||
| CORRADE_INTERNAL_ASSERT_OUTPUT(link()); | ||
|
|
||
| // set texture binding points in the shader | ||
| if (flags_ & FisheyeShader::Flag::ColorTexture) { | ||
| setUniform(uniformLocation("ColorTexture"), | ||
| fisheyeShaderTexUnitSpace::TextureUnit::Color); | ||
| } | ||
| if (flags_ & FisheyeShader::Flag::DepthTexture) { | ||
| setUniform(uniformLocation("DepthTexture"), | ||
| fisheyeShaderTexUnitSpace::TextureUnit::Depth); | ||
| } | ||
| // TODO: handle the other flags, ObjectIdTexture | ||
|
|
||
| // cache the uniform locations | ||
| // it hurts the performance to call glGetUniformLocation() every frame due | ||
| // to string operations. therefore, cache the locations in the constructor | ||
|
|
||
| focalLengthUniform_ = uniformLocation("FocalLength"); | ||
| principalPointOffsetUniform_ = uniformLocation("PrincipalPointOffset"); | ||
| alphaUniform_ = uniformLocation("Alpha"); | ||
| xiUniform_ = uniformLocation("Xi"); | ||
| } | ||
|
|
||
| DoubleSphereCameraShader& DoubleSphereCameraShader::setFocalLength( | ||
| Magnum::Vector2 focalLength) { | ||
| setUniform(focalLengthUniform_, focalLength); | ||
| return *this; | ||
| } | ||
|
|
||
| DoubleSphereCameraShader& DoubleSphereCameraShader::setPrincipalPointOffset( | ||
| Magnum::Vector2 offset) { | ||
| setUniform(principalPointOffsetUniform_, offset); | ||
| return *this; | ||
| } | ||
|
|
||
| DoubleSphereCameraShader& DoubleSphereCameraShader::setAlpha(float alpha) { | ||
| setUniform(alphaUniform_, alpha); | ||
| return *this; | ||
| } | ||
|
|
||
| DoubleSphereCameraShader& DoubleSphereCameraShader::setXi(float xi) { | ||
| setUniform(xiUniform_, xi); | ||
| return *this; | ||
| } | ||
|
|
||
| } // namespace gfx | ||
| } // namespace esp |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| // Copyright (c) Facebook, Inc. and its affiliates. | ||
| // This source code is licensed under the MIT license found in the | ||
| // LICENSE file in the root directory of this source tree. | ||
|
|
||
| #ifndef ESP_GFX_DOUBLESPHERECAMERASHADER_H_ | ||
| #define ESP_GFX_DOUBLESPHERECAMERASHADER_H_ | ||
|
|
||
| #include <Corrade/Containers/EnumSet.h> | ||
| #include <Magnum/Shaders/Generic.h> | ||
|
|
||
| #include "FisheyeShader.h" | ||
| #include "esp/core/esp.h" | ||
|
|
||
| namespace esp { | ||
| namespace gfx { | ||
| class DoubleSphereCameraShader : public FisheyeShader { | ||
| public: | ||
| enum : Magnum::UnsignedInt { | ||
| /** | ||
| * Color shader output. @ref shaders-generic "Generic output", | ||
| * present always. Expects three- or four-component floating-point | ||
| * or normalized buffer attachment. | ||
| */ | ||
| ColorOutput = Magnum::Shaders::Generic3D::ColorOutput, | ||
|
|
||
| // TODO | ||
| /** | ||
| * Object ID shader output. @ref shaders-generic "Generic output", | ||
| * present only if @ref FisheyeShader::Flag::ObjectId is set. Expects a | ||
| * single-component unsigned integral attachment. Writes the value | ||
| * set in @ref setObjectId() there. | ||
| */ | ||
| // ObjectIdOutput = Magnum::Shaders::Generic3D::ObjectIdOutput, | ||
| }; | ||
|
|
||
| explicit DoubleSphereCameraShader(FisheyeShader::Flags flags = { | ||
| FisheyeShader::Flag::ColorTexture}); | ||
|
|
||
| /** | ||
| * @brief Set the focal length of the fisheye camera | ||
| * @param focalLength, the focal length x, y directions | ||
| * @return Reference to self (for method chaining) | ||
| */ | ||
| DoubleSphereCameraShader& setFocalLength(Magnum::Vector2 focalLength); | ||
| /** | ||
| * @brief Set the offset of the principal point of the fisheye camera | ||
| * @param offset, the offset of the principal point in pixels | ||
| * @return Reference to self (for method chaining) | ||
| */ | ||
| DoubleSphereCameraShader& setPrincipalPointOffset(Magnum::Vector2 offset); | ||
| /** | ||
| * @brief Set the alpha value in the "Double Sphere Camera" model. | ||
| * See details in: | ||
| * Vladyslav Usenko, Nikolaus Demmel and Daniel Cremers: The Double Sphere | ||
| * Camera Model, The International Conference on 3D Vision (3DV), 2018 | ||
| * @param alpha, the alpha value (0.0 <= alpha < 1.0) | ||
| * @return Reference to self (for method chaining) | ||
| */ | ||
| DoubleSphereCameraShader& setAlpha(float alpha); | ||
|
|
||
| /** | ||
| * @brief Set the Xi value in the "Double Sphere Camera" model. | ||
| * See details in: | ||
| * Vladyslav Usenko, Nikolaus Demmel and Daniel Cremers: The Double Sphere | ||
| * Camera Model, The International Conference on 3D Vision (3DV), 2018 | ||
| * @param xi, the Xi value | ||
| * @return Reference to self (for method chaining) | ||
| */ | ||
| DoubleSphereCameraShader& setXi(float xi); | ||
|
|
||
| /** | ||
| * @brief deconstructor | ||
| */ | ||
| ~DoubleSphereCameraShader() override = default; | ||
|
|
||
| protected: | ||
| int focalLengthUniform_ = ID_UNDEFINED; | ||
| int principalPointOffsetUniform_ = ID_UNDEFINED; | ||
| int alphaUniform_ = ID_UNDEFINED; | ||
| int xiUniform_ = ID_UNDEFINED; | ||
| }; | ||
|
|
||
| } // namespace gfx | ||
| } // namespace esp | ||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // Copyright (c) Facebook, Inc. and its affiliates. | ||
| // This source code is licensed under the MIT license found in the | ||
| // LICENSE file in the root directory of this source tree. | ||
| #include "FisheyeShader.h" | ||
|
|
||
| #include <Corrade/Utility/Assert.h> | ||
| #include <Corrade/Utility/FormatStl.h> | ||
| #include <Corrade/Utility/Resource.h> | ||
| #include <Magnum/GL/Shader.h> | ||
| #include <Magnum/GL/Texture.h> | ||
| #include <Magnum/GL/Version.h> | ||
|
|
||
| namespace Mn = Magnum; | ||
| namespace Cr = Corrade; | ||
|
|
||
| namespace esp { | ||
| namespace gfx { | ||
| FisheyeShader::FisheyeShader(Flags flags) : flags_(flags) { | ||
| CORRADE_ASSERT(flags != Flags{}, | ||
| "FisheyeShader::FisheyeShader(): shader " | ||
| "flags cannot be empty.", ); | ||
| } | ||
| FisheyeShader& FisheyeShader::bindColorTexture( | ||
| Mn::GL::CubeMapTexture& texture) { | ||
| CORRADE_ASSERT(flags_ & FisheyeShader::Flag::ColorTexture, | ||
| "FisheyeShader::bindColorTexture(): the shader was not " | ||
| "created with color texture enabled", | ||
| *this); | ||
| texture.bind(fisheyeShaderTexUnitSpace::TextureUnit::Color); | ||
| return *this; | ||
| } | ||
|
|
||
| FisheyeShader& FisheyeShader::bindDepthTexture( | ||
| Mn::GL::CubeMapTexture& texture) { | ||
| CORRADE_ASSERT(flags_ & FisheyeShader::Flag::DepthTexture, | ||
| "FisheyeShader::bindDepthTexture(): the shader was not " | ||
| "created with depth texture enabled", | ||
| *this); | ||
| texture.bind(fisheyeShaderTexUnitSpace::TextureUnit::Depth); | ||
| return *this; | ||
| } | ||
|
|
||
| } // namespace gfx | ||
| } // namespace esp |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| // Copyright (c) Facebook, Inc. and its affiliates. | ||
| // This source code is licensed under the MIT license found in the | ||
| // LICENSE file in the root directory of this source tree. | ||
|
|
||
| #ifndef ESP_GFX_FISHEYESHADER_H_ | ||
| #define ESP_GFX_FISHEYESHADER_H_ | ||
|
|
||
| #include <Corrade/Containers/EnumSet.h> | ||
| #include <Corrade/Utility/Macros.h> | ||
| #include <Magnum/GL/AbstractShaderProgram.h> | ||
| #include <Magnum/GL/CubeMapTexture.h> | ||
| #include <Magnum/Shaders/Generic.h> | ||
|
|
||
| #include "esp/core/esp.h" | ||
|
|
||
| namespace esp { | ||
| namespace gfx { | ||
| namespace fisheyeShaderTexUnitSpace { | ||
| enum TextureUnit : uint8_t { | ||
| Color = 0, | ||
| Depth = 1, | ||
| // TODO | ||
| // ObjectId = 2, | ||
| }; | ||
| } | ||
| // Interface class for various fisheye camera shaders, such as "Double Sphere | ||
| // Camera", "Field-of-View Camera", etc. | ||
| class FisheyeShader : public Magnum::GL::AbstractShaderProgram { | ||
| public: | ||
| enum : Magnum::UnsignedInt { | ||
| /** | ||
| * Color shader output. @ref shaders-generic "Generic output", | ||
| * present always. Expects three- or four-component floating-point | ||
| * or normalized buffer attachment. | ||
| */ | ||
| ColorOutput = Magnum::Shaders::Generic3D::ColorOutput, | ||
|
|
||
| // TODO | ||
| /** | ||
| * Object ID shader output. @ref shaders-generic "Generic output", | ||
| * present only if @ref Flag::ObjectId is set. Expects a | ||
| * single-component unsigned integral attachment. Writes the value | ||
| * set in @ref setObjectId() there. | ||
| */ | ||
| // ObjectIdOutput = Magnum::Shaders::Generic3D::ObjectIdOutput, | ||
| }; | ||
|
|
||
| /** | ||
| * @brief Flag | ||
| * | ||
| * @see @ref Flags, @ref flags() | ||
| */ | ||
| enum class Flag : Magnum::UnsignedShort { | ||
| /** | ||
| * cubemap color texture | ||
| */ | ||
| ColorTexture = 1 << 0, | ||
| /** | ||
| * cubemap depth texture | ||
| */ | ||
| DepthTexture = 1 << 1, | ||
| // ObjectIdTexture = 1 << 2, | ||
| }; | ||
|
|
||
| typedef Corrade::Containers::EnumSet<Flag> Flags; | ||
|
|
||
| /** | ||
| * @brief constructor | ||
| * @param[in] flags fisheye shader flags | ||
| */ | ||
| explicit FisheyeShader(Flags flags = {Flag::ColorTexture}); | ||
|
|
||
| ~FisheyeShader() override = default; | ||
|
|
||
| /** @brief Flags */ | ||
| Flags flags() const { return flags_; } | ||
|
|
||
| /** | ||
| * @brief bind cubemap color texture | ||
| * @param[in] texture cubemap color texture | ||
| */ | ||
| virtual FisheyeShader& bindColorTexture(Magnum::GL::CubeMapTexture& texture); | ||
| /** | ||
| * @brief bind cubemap depth texture | ||
| * @param[in] texture cubemap depth texture | ||
| */ | ||
| virtual FisheyeShader& bindDepthTexture(Magnum::GL::CubeMapTexture& texture); | ||
| // virtual FisheyeShader& bindObjectIdTexture(Magnum::GL::Texture2D& | ||
| // texture); | ||
|
|
||
| protected: | ||
| Flags flags_; | ||
| }; | ||
| CORRADE_ENUMSET_OPERATORS(FisheyeShader::Flags) | ||
| } // namespace gfx | ||
| } // namespace esp | ||
| #endif |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.