diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-04-12 17:54:45 -0500 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-04-12 17:54:45 -0500 |
| commit | a0355c9b897281d0bfea48bec9d490724ecabd96 (patch) | |
| tree | 42c56ea4f4829a6115f688956858ada3e59fd9ef /libs/preview_nif/src/TextureManager.h | |
| parent | fa43a71f9d05b3673d42296a80decb2228d68f83 (diff) | |
Add NIF previewer plugin with Linux-specific fixes
Vendored from github.com/Parapets/mo2-preview_nif and adapted for Linux:
- BSA texture resolution via MO2 virtual tree with case-insensitive
fallback walk (Linux FS is case-sensitive; NIFs reference textures
with arbitrary case against files on disk)
- Process-wide cached BSA candidate list, keyed by profile path,
priority-sorted, filtering disabled mods
- Path backslash normalization before loose-file lookup
- Polygon offset on SLSF1_Decal-flagged shapes to break z-ties with
coincident base meshes (road decals, moss overlays)
- Opaque framebuffer via glColorMask alpha lock so alpha-blended shapes
can't bleed the dialog background through the preview area
- QMouseEvent::globalPosition().toPoint() for Qt6 compatibility
Preview dialog behavior (organizercore.cpp):
- Switch previewFile and previewFileWithAlternatives from stack-allocated
exec() to heap + ApplicationModal + show() + WA_DeleteOnClose.
- Parent passed as nullptr so preview lifetime is decoupled from the
stack-allocated ModInfoDialog that spawns it. Nested exec() inside
the enclosing dialog's exec() was softlocking on close.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'libs/preview_nif/src/TextureManager.h')
| -rw-r--r-- | libs/preview_nif/src/TextureManager.h | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/libs/preview_nif/src/TextureManager.h b/libs/preview_nif/src/TextureManager.h new file mode 100644 index 0000000..7ba1c9a --- /dev/null +++ b/libs/preview_nif/src/TextureManager.h @@ -0,0 +1,53 @@ +#pragma once + +#include <imoinfo.h> +#include <gli/gli.hpp> +#include <QOpenGLTexture> +#include <QSet> +#include <QStringList> +#include <map> + +class TextureManager +{ +public: + TextureManager(MOBase::IOrganizer* organizer); + ~TextureManager() = default; + TextureManager(const TextureManager&) = delete; + TextureManager(TextureManager&&) = delete; + TextureManager& operator=(const TextureManager&) = delete; + TextureManager& operator=(TextureManager&&) = delete; + + void cleanup(); + + QOpenGLTexture* getTexture(const std::string& texturePath); + QOpenGLTexture* getTexture(QString texturePath); + + QOpenGLTexture* getErrorTexture(); + QOpenGLTexture* getBlackTexture(); + QOpenGLTexture* getWhiteTexture(); + QOpenGLTexture* getFlatNormalTexture(); + +private: + QOpenGLTexture* loadTexture(QString texturePath); + QOpenGLTexture* makeTexture(const gli::texture& texture); + QOpenGLTexture* makeSolidColor(QVector4D color); + + QString resolvePath(const MOBase::IPluginGame* game, QString path); + + // Build priority-sorted BSA candidate list. Shared process-wide, keyed by + // the current instance's profile path so switching instances rebuilds. + // Conflict semantics: only active mods contribute, highest profile + // priority first, then vanilla archives. No plugin-attachment filter — + // matches BodySlide's "load all BSAs" approach which is what MO2's + // virtual data tree effectively does. + const QStringList& bsaCandidates(); + void rebuildBsaCandidates(); + + MOBase::IOrganizer* m_MOInfo; + QOpenGLTexture* m_ErrorTexture = nullptr; + QOpenGLTexture* m_BlackTexture = nullptr; + QOpenGLTexture* m_WhiteTexture = nullptr; + QOpenGLTexture* m_FlatNormalTexture = nullptr; + + std::map<std::wstring, QOpenGLTexture*> m_Textures; +}; |
