diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..4bb1166 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,28 @@ +name: Build NIF Preview Plugin + +on: + push: + branches: main + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: windows-2022 + steps: + - name: Build NIF Preview Plugin + uses: ModOrganizer2/build-with-mob-action@master + with: + mo2-third-parties: fmt libbsarch + mo2-dependencies: cmake_common uibase + - name: Upload Build + uses: actions/upload-artifact@v3 + with: + name: preview_nif + path: | + ./build/modorganizer_super/${{ github.event.repository.name }}/vsbuild/src/RelWithDebInfo/preview_nif.dll + - uses: actions/upload-artifact@v3 + with: + name: preview_nif + path: | + ./build/modorganizer_super/${{ github.event.repository.name }}/**/data/shaders/* diff --git a/.gitmodules b/.gitmodules index 2ab6019..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +0,0 @@ -[submodule "external/nifly"] - path = external/nifly - url = https://github.com/ousnius/nifly.git -[submodule "external/gli"] - path = external/gli - url = https://github.com/g-truc/gli.git diff --git a/CMakeLists.txt b/CMakeLists.txt index a61fa50..5d5dd5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,29 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 3.22) + +if(DEFINED DEPENDENCIES_DIR) + include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/mo2.cmake) +else() + include(${CMAKE_CURRENT_LIST_DIR}/cmake_common/mo2.cmake) +endif() project(preview_nif) set(project_type plugin) set(enable_warnings OFF) -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake) -else() - include(../cmake_common/project.cmake) -endif() -add_subdirectory(src) +FetchContent_Declare( + gli + GIT_REPOSITORY https://github.com/g-truc/gli.git + GIT_TAG master +) set(GLI_TEST_ENABLE OFF CACHE BOOL "Build gli unit tests") -add_subdirectory(external/gli) -add_subdirectory(external/nifly) -target_link_libraries(${PROJECT_NAME} nifly gli) + +FetchContent_Declare( + nifly + GIT_REPOSITORY https://github.com/ousnius/nifly.git + GIT_TAG main +) + +FetchContent_MakeAvailable(gli nifly) + +add_subdirectory(src) +target_link_libraries(preview_nif PRIVATE nifly gli) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..d00c664 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,72 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "windows-2022", + "generator": "Visual Studio 17 2022", + "binaryDir": "${sourceDir}/vsbuild", + "cacheVariables": { + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "DEPENDENCIES_DIR": { + "type": "PATH", + "value": "${sourceDir}/../.." + }, + "BOOST_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../boost_1_83_0" + }, + "BOOST_LIBRARYDIR": { + "type": "PATH", + "value": "${sourceDir}/../../boost_1_83_0/lib64-msvc-14.3/lib" + }, + "FMT_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../fmt-8.1.1" + }, + "SPDLOG_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../spdlog-v1.10.0" + }, + "LOOT_PATH": { + "type": "PATH", + "value": "${sourceDir}/../../libloot-0.22.1-win64" + }, + "LZ4_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../lz4-v1.9.4" + }, + "QT_ROOT": { + "type": "PATH", + "value": "C:/Qt/6.5.3/msvc2019_64" + }, + "ZLIB_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../zlib-v1.3" + }, + "PYTHON_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../python-3.11.5" + }, + "SEVENZ_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../7zip-23.01" + }, + "LIBBSARCH_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../libbsarch-0.0.9-release-x64" + }, + "BOOST_DI_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../di" + }, + "GTEST_ROOT": { + "type": "PATH", + "value": "${sourceDir}/../../googletest" + } + } + } + ] +} \ No newline at end of file diff --git a/external/gli b/external/gli deleted file mode 160000 index 779b99a..0000000 --- a/external/gli +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 779b99ac6656e4d30c3b24e96e0136a59649a869 diff --git a/external/nifly b/external/nifly deleted file mode 160000 index 5504832..0000000 --- a/external/nifly +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5504832da8009248ff68a9d306973ee1ba61a0a4 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 86d062b..512aed3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,9 @@ -cmake_minimum_required(VERSION 3.16) -if(DEFINED DEPENDENCIES_DIR) - include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake) -else() - include(../../cmake_common/src.cmake) -endif() -requires_library(libbsarch) -requires_project(game_features) +cmake_minimum_required(VERSION 3.22) + +add_library(preview_nif SHARED) +mo2_configure_plugin( + preview_nif + WARNINGS OFF + PRIVATE_DEPENDS Qt::OpenGLWidgets fmt libbsarch uibase +) +mo2_install_target(preview_nif) diff --git a/src/NifWidget.cpp b/src/NifWidget.cpp index 4edd2ed..f6340f0 100644 --- a/src/NifWidget.cpp +++ b/src/NifWidget.cpp @@ -5,6 +5,7 @@ #include #include #include +#include using OpenGLFunctions = QOpenGLFunctions_2_1; NifWidget::NifWidget( @@ -131,7 +132,8 @@ void NifWidget::initializeGL() update(); }); - auto f = QOpenGLContext::currentContext()->versionFunctions(); + auto f = QOpenGLVersionFunctionsFactory::get( + QOpenGLContext::currentContext()); f->glEnable(GL_DEPTH_TEST); f->glDepthFunc(GL_LEQUAL); @@ -140,7 +142,8 @@ void NifWidget::initializeGL() void NifWidget::paintGL() { - auto f = QOpenGLContext::currentContext()->versionFunctions(); + auto f = QOpenGLVersionFunctionsFactory::get( + QOpenGLContext::currentContext()); f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (auto& shape : m_GLShapes) { diff --git a/src/OpenGLShape.cpp b/src/OpenGLShape.cpp index 9184c21..a65cb15 100644 --- a/src/OpenGLShape.cpp +++ b/src/OpenGLShape.cpp @@ -3,6 +3,7 @@ #include #include +#include template inline static QOpenGLBuffer* makeVertexBuffer(const std::vector* data, GLuint attrib) @@ -14,18 +15,13 @@ inline static QOpenGLBuffer* makeVertexBuffer(const std::vector* data, GLuint if (buffer->create() && buffer->bind()) { buffer->allocate(data->data(), data->size() * sizeof(T)); - auto f = QOpenGLContext::currentContext() - ->versionFunctions(); + auto f = QOpenGLVersionFunctionsFactory::get( + QOpenGLContext::currentContext()); f->glEnableVertexAttribArray(attrib); - f->glVertexAttribPointer( - attrib, - sizeof(T) / sizeof(float), - GL_FLOAT, - GL_FALSE, - sizeof(T), - nullptr); + f->glVertexAttribPointer(attrib, sizeof(T) / sizeof(float), GL_FLOAT, + GL_FALSE, sizeof(T), nullptr); buffer->release(); } @@ -34,14 +30,13 @@ inline static QOpenGLBuffer* makeVertexBuffer(const std::vector* data, GLuint return buffer; } -OpenGLShape::OpenGLShape( - nifly::NifFile* nifFile, - nifly::NiShape* niShape, - TextureManager* textureManager) +OpenGLShape::OpenGLShape(nifly::NifFile* nifFile, nifly::NiShape* niShape, + TextureManager* textureManager) { - auto f = QOpenGLContext::currentContext()->versionFunctions(); + auto f = QOpenGLVersionFunctionsFactory::get( + QOpenGLContext::currentContext()); - auto shader = nifFile->GetShader(niShape); + auto shader = nifFile->GetShader(niShape); auto& version = nifFile->GetHeader().GetVersion(); if (version.IsFO4()) { if (shader && shader->HasType()) { @@ -59,7 +54,8 @@ OpenGLShape::OpenGLShape( if (shader && shader->IsModelSpace()) { shaderType = ShaderManager::SKMSN; } - else if (shader && shader->GetShaderType() == nifly::BSLSP_MULTILAYERPARALLAX) { + else if (shader && + shader->GetShaderType() == nifly::BSLSP_MULTILAYERPARALLAX) { shaderType = ShaderManager::SKMultilayer; } else { @@ -72,7 +68,7 @@ OpenGLShape::OpenGLShape( vertexArray->create(); auto binder = QOpenGLVertexArrayObject::Binder(vertexArray); - auto xform = GetShapeTransformToGlobal(nifFile, niShape); + auto xform = GetShapeTransformToGlobal(nifFile, niShape); modelMatrix = convertTransform(xform); f->glVertexAttrib2f(AttribTexCoord, 0.0f, 0.0f); @@ -121,7 +117,8 @@ OpenGLShape::OpenGLShape( vertexBuffers[AttribTexCoord] = makeVertexBuffer(uvs, AttribTexCoord); } - if (std::vector colors; nifFile->GetColorsForShape(niShape, colors)) { + if (std::vector colors; + nifFile->GetColorsForShape(niShape, colors)) { vertexBuffers[AttribColor] = makeVertexBuffer(&colors, AttribColor); } @@ -139,7 +136,7 @@ OpenGLShape::OpenGLShape( if (shader) { if (shader->HasTextureSet()) { auto textureSetRef = shader->TextureSetRef(); - auto textureSet = nifFile->GetHeader().GetBlock(textureSetRef); + auto textureSet = nifFile->GetHeader().GetBlock(textureSetRef); for (std::size_t i = 0; i < textureSet->textures.size(); i++) { auto texturePath = textureSet->textures[i].get(); @@ -171,61 +168,61 @@ OpenGLShape::OpenGLShape( } } - specColor = convertVector3(shader->GetSpecularColor()); - specStrength = shader->GetSpecularStrength(); + specColor = convertVector3(shader->GetSpecularColor()); + specStrength = shader->GetSpecularStrength(); specGlossiness = qBound(0.0f, shader->GetGlossiness(), 128.0f); - fresnelPower = shader->GetFresnelPower(); - paletteScale = shader->GetGrayscaleToPaletteScale(); + fresnelPower = shader->GetFresnelPower(); + paletteScale = shader->GetGrayscaleToPaletteScale(); hasGlowMap = shader->HasGlowmap(); - glowColor = convertColor(shader->GetEmissiveColor()); - glowMult = shader->GetEmissiveMultiple(); + glowColor = convertColor(shader->GetEmissiveColor()); + glowMult = shader->GetEmissiveMultiple(); - alpha = shader->GetAlpha(); - uvScale = convertVector2(shader->GetUVScale()); + alpha = shader->GetAlpha(); + uvScale = convertVector2(shader->GetUVScale()); uvOffset = convertVector2(shader->GetUVOffset()); - hasEmit = shader->IsEmissive(); + hasEmit = shader->IsEmissive(); hasSoftlight = shader->HasSoftlight(); hasBacklight = shader->HasBacklight(); - hasRimlight = shader->HasRimlight(); + hasRimlight = shader->HasRimlight(); - softlight = shader->GetSoftlight(); + softlight = shader->GetSoftlight(); backlightPower = shader->GetBacklightPower(); - rimPower = shader->GetRimlightPower(); - doubleSided = shader->IsDoubleSided(); - envReflection = shader->GetEnvironmentMapScale(); + rimPower = shader->GetRimlightPower(); + doubleSided = shader->IsDoubleSided(); + envReflection = shader->GetEnvironmentMapScale(); if (auto alphaProperty = nifFile->GetAlphaProperty(niShape)) { NiAlphaPropertyFlags flags = alphaProperty->flags; alphaBlendEnable = flags.isAlphaBlendEnabled(); - srcBlendMode = flags.sourceBlendingFactor(); - dstBlendMode = flags.destinationBlendingFactor(); - alphaTestEnable = flags.isAlphaTestEnabled(); - alphaTestMode = flags.alphaTestMode(); + srcBlendMode = flags.sourceBlendingFactor(); + dstBlendMode = flags.destinationBlendingFactor(); + alphaTestEnable = flags.isAlphaTestEnabled(); + alphaTestMode = flags.alphaTestMode(); alphaThreshold = alphaProperty->threshold / 255.0f; } if (auto bslsp = dynamic_cast(shader)) { - zBufferTest = bslsp->shaderFlags1 & SLSF1::ZBufferTest; + zBufferTest = bslsp->shaderFlags1 & SLSF1::ZBufferTest; zBufferWrite = bslsp->shaderFlags2 & SLSF2::ZBufferWrite; auto bslspType = bslsp->GetShaderType(); if (bslspType == nifly::BSLSP_SKINTINT || bslspType == nifly::BSLSP_FACE) { - tintColor = convertVector3(bslsp->skinTintColor); + tintColor = convertVector3(bslsp->skinTintColor); hasTintColor = true; } else if (bslspType == nifly::BSLSP_HAIRTINT) { - tintColor = convertVector3(bslsp->hairTintColor); + tintColor = convertVector3(bslsp->hairTintColor); hasTintColor = true; } if (bslspType == nifly::BSLSP_MULTILAYERPARALLAX) { - innerScale = convertVector2(bslsp->parallaxInnerLayerTextureScale); - innerThickness = bslsp->parallaxInnerLayerThickness; + innerScale = convertVector2(bslsp->parallaxInnerLayerTextureScale); + innerThickness = bslsp->parallaxInnerLayerThickness; outerRefraction = bslsp->parallaxRefractionScale; outerReflection = bslsp->parallaxEnvmapStrength; } @@ -236,7 +233,7 @@ OpenGLShape::OpenGLShape( } } else { - textures[BaseMap] = textureManager->getWhiteTexture(); + textures[BaseMap] = textureManager->getWhiteTexture(); textures[NormalMap] = textureManager->getFlatNormalTexture(); } } @@ -327,7 +324,8 @@ void OpenGLShape::setupShaders(QOpenGLShaderProgram* program) program->setUniformValue("outerReflection", outerReflection); } - auto f = QOpenGLContext::currentContext()->versionFunctions(); + auto f = QOpenGLVersionFunctionsFactory::get( + QOpenGLContext::currentContext()); for (std::size_t i = 0; i < ATTRIB_COUNT; i++) { if (vertexBuffers[i]) { @@ -374,12 +372,12 @@ void OpenGLShape::setupShaders(QOpenGLShaderProgram* program) QVector2D OpenGLShape::convertVector2(nifly::Vector2 vector) { - return { vector.u, vector.v }; + return {vector.u, vector.v}; } QVector3D OpenGLShape::convertVector3(nifly::Vector3 vector) { - return { vector.x, vector.y, vector.z }; + return {vector.x, vector.y, vector.z}; } QColor OpenGLShape::convertColor(nifly::Color4 color) @@ -391,9 +389,7 @@ QMatrix4x4 OpenGLShape::convertTransform(nifly::MatTransform transform) { auto mat = transform.ToMatrix(); return QMatrix4x4{ - mat[0], mat[1], mat[2], mat[3], - mat[4], mat[5], mat[6], mat[7], - mat[8], mat[9], mat[10], mat[11], - mat[12], mat[13], mat[14], mat[15], + mat[0], mat[1], mat[2], mat[3], mat[4], mat[5], mat[6], mat[7], + mat[8], mat[9], mat[10], mat[11], mat[12], mat[13], mat[14], mat[15], }; } diff --git a/src/PreviewNif.cpp b/src/PreviewNif.cpp index 6b3a342..86a1f97 100644 --- a/src/PreviewNif.cpp +++ b/src/PreviewNif.cpp @@ -30,7 +30,7 @@ QString PreviewNif::description() const MOBase::VersionInfo PreviewNif::version() const { - return MOBase::VersionInfo(0, 1, 8, 1, MOBase::VersionInfo::RELEASE_BETA); + return MOBase::VersionInfo(0, 2, 0, 0, MOBase::VersionInfo::RELEASE_BETA); } QList PreviewNif::settings() const @@ -45,7 +45,7 @@ bool PreviewNif::enabledByDefault() const std::set PreviewNif::supportedExtensions() const { - return { "nif" }; + return { "bto", "btr", "nif" }; } QWidget* PreviewNif::genFilePreview(const QString& fileName, const QSize& maxSize) const diff --git a/src/TextureManager.cpp b/src/TextureManager.cpp index 19e0162..b6b75ed 100644 --- a/src/TextureManager.cpp +++ b/src/TextureManager.cpp @@ -1,20 +1,20 @@ #include "TextureManager.h" #include "PreviewNif.h" -#include #include +#include #include #include #include #include +#include #include #include -TextureManager::TextureManager(MOBase::IOrganizer* moInfo) : m_MOInfo{ moInfo } -{} +TextureManager::TextureManager(MOBase::IOrganizer* moInfo) : m_MOInfo{moInfo} {} void TextureManager::cleanup() { @@ -72,7 +72,7 @@ QOpenGLTexture* TextureManager::getTexture(QString texturePath) QOpenGLTexture* TextureManager::getErrorTexture() { if (!m_ErrorTexture) { - m_ErrorTexture = makeSolidColor({ 1.0f, 0.0f, 1.0f, 1.0f }); + m_ErrorTexture = makeSolidColor({1.0f, 0.0f, 1.0f, 1.0f}); } return m_ErrorTexture; @@ -81,7 +81,7 @@ QOpenGLTexture* TextureManager::getErrorTexture() QOpenGLTexture* TextureManager::getBlackTexture() { if (!m_BlackTexture) { - m_BlackTexture = makeSolidColor({ 0.0f, 0.0f, 0.0f, 1.0f }); + m_BlackTexture = makeSolidColor({0.0f, 0.0f, 0.0f, 1.0f}); } return m_BlackTexture; @@ -90,7 +90,7 @@ QOpenGLTexture* TextureManager::getBlackTexture() QOpenGLTexture* TextureManager::getWhiteTexture() { if (!m_WhiteTexture) { - m_WhiteTexture = makeSolidColor({ 1.0f, 1.0f, 1.0f, 1.0f }); + m_WhiteTexture = makeSolidColor({1.0f, 1.0f, 1.0f, 1.0f}); } return m_WhiteTexture; @@ -99,7 +99,7 @@ QOpenGLTexture* TextureManager::getWhiteTexture() QOpenGLTexture* TextureManager::getFlatNormalTexture() { if (!m_FlatNormalTexture) { - m_FlatNormalTexture = makeSolidColor({ 0.5f, 0.5f, 1.0f, 1.0f }); + m_FlatNormalTexture = makeSolidColor({0.5f, 0.5f, 1.0f, 1.0f}); } return m_FlatNormalTexture; @@ -114,7 +114,8 @@ QOpenGLTexture* TextureManager::loadTexture(QString texturePath) auto game = m_MOInfo->managedGame(); if (!game) { - qCritical(qUtf8Printable(QObject::tr("Failed to interface with managed game plugin"))); + qCritical(qUtf8Printable( + QObject::tr("Failed to interface with managed game plugin"))); return nullptr; } @@ -138,29 +139,29 @@ QOpenGLTexture* TextureManager::loadTexture(QString texturePath) } using bsa_ptr = std::unique_ptr; - auto bsa = bsa_ptr(bsa_create(), bsa_free); + auto bsa = bsa_ptr(bsa_create(), bsa_free); static_assert(sizeof(wchar_t) == 2, "Expected wchar_t to be 2 bytes"); bsa_result_message_t result; auto bsaPath_utf16 = reinterpret_cast(bsaPath.utf16()); - result = bsa_load_from_file(bsa.get(), bsaPath_utf16); + result = bsa_load_from_file(bsa.get(), bsaPath_utf16); if (result.code == BSA_RESULT_EXCEPTION) { continue; } auto texturePath_utf16 = reinterpret_cast(texturePath.utf16()); - auto result_buffer = bsa_extract_file_data_by_filename(bsa.get(), texturePath_utf16); + auto result_buffer = + bsa_extract_file_data_by_filename(bsa.get(), texturePath_utf16); if (result_buffer.message.code == BSA_RESULT_EXCEPTION) { continue; } - auto buffer_free = - [&bsa](bsa_result_buffer_t* buffer) { - bsa_file_data_free(bsa.get(), *buffer); - }; + auto buffer_free = [&bsa](bsa_result_buffer_t* buffer) { + bsa_file_data_free(bsa.get(), *buffer); + }; using buffer_ptr = std::unique_ptr; - auto buffer = buffer_ptr(&result_buffer.buffer, buffer_free); + auto buffer = buffer_ptr(&result_buffer.buffer, buffer_free); auto data = static_cast(buffer->data); if (auto texture = makeTexture(gli::load(data, buffer->size))) { @@ -179,17 +180,20 @@ QOpenGLTexture* TextureManager::makeTexture(const gli::texture& texture) gli::gl GL(gli::gl::PROFILE_GL32); const gli::gl::format format = GL.translate(texture.format(), texture.swizzles()); - GLenum target = GL.translate(texture.target()); + GLenum target = GL.translate(texture.target()); - auto f = QOpenGLContext::currentContext()->versionFunctions(); - QOpenGLTexture* glTexture = new QOpenGLTexture(static_cast(target)); + auto f = QOpenGLVersionFunctionsFactory::get( + QOpenGLContext::currentContext()); + QOpenGLTexture* glTexture = + new QOpenGLTexture(static_cast(target)); glTexture->create(); glTexture->bind(); glTexture->setMipLevels(texture.levels()); glTexture->setMipBaseLevel(0); glTexture->setMipMaxLevel(texture.levels() - 1); - glTexture->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); + glTexture->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, + QOpenGLTexture::Linear); glTexture->setSwizzleMask( static_cast(format.Swizzles[0]), static_cast(format.Swizzles[1]), @@ -198,7 +202,7 @@ QOpenGLTexture* TextureManager::makeTexture(const gli::texture& texture) glTexture->setWrapMode(QOpenGLTexture::Repeat); - auto extent = texture.extent(); + auto extent = texture.extent(); const GLsizei faceTotal = texture.layers() * texture.faces(); glTexture->setSize(extent.x, extent.y, extent.z); @@ -208,93 +212,67 @@ QOpenGLTexture* TextureManager::makeTexture(const gli::texture& texture) static_cast(format.Type)); for (std::size_t layer = 0; layer < texture.layers(); layer++) - for (std::size_t face = 0; face < texture.faces(); face++) - for (std::size_t level = 0; level < texture.levels(); level++) - { - auto extent = texture.extent(level); - - target = gli::is_target_cube(texture.target()) - ? static_cast(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face) - : target; - - // Qt's upload functions lag badly so we just use the GL API - switch (texture.target()) { - case gli::TARGET_1D: - if (gli::is_compressed(texture.format())) { - f->glCompressedTexSubImage1D( - target, - level, - 0, - extent.x, - format.Internal, - texture.size(level), - texture.data(layer, face, level)); - } - else { - f->glTexSubImage1D( - target, - level, - 0, - extent.x, - format.External, - format.Type, - texture.data(layer, face, level)); - } - break; - case gli::TARGET_1D_ARRAY: - case gli::TARGET_2D: - case gli::TARGET_CUBE: - if (gli::is_compressed(texture.format())) { - f->glCompressedTexSubImage2D( - target, - level, - 0, 0, - extent.x, - texture.target() == gli::TARGET_1D_ARRAY ? layer : extent.y, - format.Internal, - texture.size(level), - texture.data(layer, face, level)); - } - else { - f->glTexSubImage2D( - target, - level, - 0, 0, - extent.x, - texture.target() == gli::TARGET_1D_ARRAY ? layer : extent.y, - format.External, - format.Type, - texture.data(layer, face, level)); + for (std::size_t face = 0; face < texture.faces(); face++) + for (std::size_t level = 0; level < texture.levels(); level++) { + auto extent = texture.extent(level); + + target = + gli::is_target_cube(texture.target()) + ? static_cast(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face) + : target; + + // Qt's upload functions lag badly so we just use the GL API + switch (texture.target()) { + case gli::TARGET_1D: + if (gli::is_compressed(texture.format())) { + f->glCompressedTexSubImage1D( + target, level, 0, extent.x, format.Internal, + texture.size(level), texture.data(layer, face, level)); + } + else { + f->glTexSubImage1D(target, level, 0, extent.x, format.External, + format.Type, + texture.data(layer, face, level)); + } + break; + case gli::TARGET_1D_ARRAY: + case gli::TARGET_2D: + case gli::TARGET_CUBE: + if (gli::is_compressed(texture.format())) { + f->glCompressedTexSubImage2D( + target, level, 0, 0, extent.x, + texture.target() == gli::TARGET_1D_ARRAY ? layer : extent.y, + format.Internal, texture.size(level), + texture.data(layer, face, level)); + } + else { + f->glTexSubImage2D( + target, level, 0, 0, extent.x, + texture.target() == gli::TARGET_1D_ARRAY ? layer : extent.y, + format.External, format.Type, + texture.data(layer, face, level)); + } + break; + case gli::TARGET_2D_ARRAY: + case gli::TARGET_3D: + case gli::TARGET_CUBE_ARRAY: + if (gli::is_compressed(texture.format())) { + f->glCompressedTexSubImage3D( + target, level, 0, 0, 0, extent.x, extent.y, + texture.target() == gli::TARGET_3D ? extent.z : layer, + format.Internal, texture.size(level), + texture.data(layer, face, level)); + } + else { + f->glTexSubImage3D(target, level, 0, 0, 0, extent.x, extent.y, + texture.target() == gli::TARGET_3D ? extent.z + : layer, + format.External, format.Type, + texture.data(layer, face, level)); + } + break; + } } - break; - case gli::TARGET_2D_ARRAY: - case gli::TARGET_3D: - case gli::TARGET_CUBE_ARRAY: - if (gli::is_compressed(texture.format())) { - f->glCompressedTexSubImage3D( - target, - level, - 0, 0, 0, - extent.x, extent.y, - texture.target() == gli::TARGET_3D ? extent.z : layer, - format.Internal, - texture.size(level), - texture.data(layer, face, level)); - } - else { - f->glTexSubImage3D( - target, - level, - 0, 0, 0, - extent.x, extent.y, - texture.target() == gli::TARGET_3D ? extent.z : layer, - format.External, - format.Type, - texture.data(layer, face, level)); - } - break; - } - } glTexture->release(); diff --git a/src/preview_nif_en.ts b/src/preview_nif_en.ts index bc7279e..10b8b07 100644 --- a/src/preview_nif_en.ts +++ b/src/preview_nif_en.ts @@ -4,6 +4,7 @@ NifWidget + OpenGL debug message: %1 @@ -11,10 +12,12 @@ PreviewNif + Failed to load file: %1 + Verts: %1 | Faces: %2 | Shapes: %3 @@ -22,6 +25,7 @@ QObject + Failed to interface with managed game plugin