From 892070f3dec1dc690983fd862880e37e711c2516 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Sun, 12 Apr 2026 17:55:56 -0500 Subject: Add BSA in-memory extraction and nested preview support bsatk: - Archive::extractToMemory() extracts a file directly into a byte buffer instead of a filesystem path, backed by a std::ostringstream sink. - Archive::findFile() locates a file by relative path, case-insensitive and separator-agnostic, walking the folder tree recursively. - extractDirect/extractCompressed now take std::ostream& so both the ofstream and ostringstream paths share the same implementation. libbsarch: shim rewrite on Linux to map the Windows API surface onto bsatk::Archive, enabling preview_bsa to open vanilla BSAs via the same interface as other plugins. preview_bsa: double-click on a file in the BSA tree now extracts the bytes via extractToMemory() and hands them to IOrganizer::previewFileData for nested preview rendering (e.g. NIF inside a BSA). uibase + organizerproxy + organizercore: new IOrganizer::previewFileData virtual that routes in-memory file bytes through the first registered IPluginPreview matching the extension. Uses heap + WA_DeleteOnClose + open() to avoid nested exec() softlock from mod info filetree -> preview_bsa tree -> nif preview. docker/build-inner.sh: stage preview_nif shaders into plugin_data/shaders so ShaderManager can load them via IOrganizer::getPluginDataPath(). Co-Authored-By: Claude Opus 4.6 (1M context) --- src/src/organizercore.h | 2 ++ src/src/organizerproxy.cpp | 6 ++++++ src/src/organizerproxy.h | 3 +++ 3 files changed, 11 insertions(+) (limited to 'src') diff --git a/src/src/organizercore.h b/src/src/organizercore.h index dc3547e..834b8a7 100644 --- a/src/src/organizercore.h +++ b/src/src/organizercore.h @@ -337,6 +337,8 @@ public: bool previewFileWithAlternatives(QWidget* parent, QString filename, int selectedOrigin = -1); bool previewFile(QWidget* parent, const QString& originName, const QString& path); + bool previewFileData(QWidget* parent, const QString& fileName, + const QByteArray& fileData); void loginSuccessfulUpdate(bool necessary); void loginFailedUpdate(const QString& message); diff --git a/src/src/organizerproxy.cpp b/src/src/organizerproxy.cpp index 80603f0..02e1e20 100644 --- a/src/src/organizerproxy.cpp +++ b/src/src/organizerproxy.cpp @@ -387,6 +387,12 @@ MOBase::IGameFeatures* OrganizerProxy::gameFeatures() const return m_GameFeaturesProxy.get(); } +bool OrganizerProxy::previewFileData(QWidget* parent, const QString& fileName, + const QByteArray& fileData) +{ + return m_Proxied->previewFileData(parent, fileName, fileData); +} + std::shared_ptr OrganizerProxy::profile() const { return m_Proxied->currentProfile(); diff --git a/src/src/organizerproxy.h b/src/src/organizerproxy.h index f1ede58..ce52d39 100644 --- a/src/src/organizerproxy.h +++ b/src/src/organizerproxy.h @@ -75,6 +75,9 @@ public: // IOrganizer interface MOBase::IGameFeatures* gameFeatures() const override; MOBase::IInstanceManager* instanceManager() const override { return nullptr; } + bool previewFileData(QWidget* parent, const QString& fileName, + const QByteArray& fileData) override; + HANDLE startApplication(const QString& executable, const QStringList& args = QStringList(), const QString& cwd = "", const QString& profile = "", -- cgit v1.3.1