Переглянути джерело

~ Removed static variables in namespace WallpaperEngine::Irrlicht and moved to a context approach
This includes changes to old code to be compatible, the externs won't be used once the renderer is rewritten and the old code removed

Signed-off-by: Alexis Maiquez <almamu@almamu.com>

Alexis Maiquez 7 роки тому
батько
коміт
b8b3c2899d

+ 2 - 2
CMakeLists.txt

@@ -48,14 +48,14 @@ add_executable(
         src/WallpaperEngine/video/material.h
         src/WallpaperEngine/texture.cpp
         src/WallpaperEngine/texture.h
+        src/WallpaperEngine/Irrlicht/CContext.h
+        src/WallpaperEngine/Irrlicht/CContext.cpp
         src/WallpaperEngine/Irrlicht/CImageLoaderTEX.h
         src/WallpaperEngine/Irrlicht/CImageLoaderTEX.cpp
         src/WallpaperEngine/Irrlicht/CPkgReader.h
         src/WallpaperEngine/Irrlicht/CPkgReader.cpp
         src/WallpaperEngine/Irrlicht/CFileList.h
         src/WallpaperEngine/Irrlicht/CFileList.cpp
-        src/WallpaperEngine/Irrlicht/Irrlicht.cpp
-        src/WallpaperEngine/Irrlicht/Irrlicht.h
         src/WallpaperEngine/sound.cpp
         src/WallpaperEngine/sound.h
 

+ 41 - 25
main.cpp

@@ -8,20 +8,26 @@
 #include <SDL_mixer.h>
 #include <SDL.h>
 
+#include <X11/Xlib.h>
+
 #include "WallpaperEngine/Render/Shaders/Compiler.h"
 #include "WallpaperEngine/project.h"
-#include "WallpaperEngine/Irrlicht/Irrlicht.h"
 #include "WallpaperEngine/Irrlicht/CImageLoaderTEX.h"
 
 #include "WallpaperEngine/Core/CProject.h"
+#include "WallpaperEngine/Irrlicht/CContext.h"
 
 int WinID = 0;
 irr::SIrrlichtCreationParameters _irr_params;
 
 irr::f32 g_Time = 0;
 
+WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
+
 int init_irrlicht()
 {
+    IrrlichtContext = new WallpaperEngine::Irrlicht::CContext ();
+
     // prepare basic configuration for irrlicht
     _irr_params.AntiAlias = 8;
     _irr_params.Bits = 16;
@@ -38,31 +44,34 @@ int init_irrlicht()
     _irr_params.WithAlphaChannel = false;
     _irr_params.ZBufferBits = 24;
     _irr_params.LoggingLevel = irr::ELL_DEBUG;
-    _irr_params.WindowId = reinterpret_cast<void*> (WinID);
 
-    WallpaperEngine::Irrlicht::device = irr::createDeviceEx (_irr_params);
+    Display* display = XOpenDisplay (NULL);
+    int screen = XDefaultScreen (display);
 
-    if (WallpaperEngine::Irrlicht::device == nullptr)
+    _irr_params.WindowId = reinterpret_cast<void*> (XRootWindow (display, screen));
+
+    IrrlichtContext->setDevice (irr::createDeviceEx (_irr_params));
+
+    if (IrrlichtContext->getDevice () == nullptr)
     {
         return 1;
     }
 
-    WallpaperEngine::Irrlicht::device->setWindowCaption (L"Test game");
-    WallpaperEngine::Irrlicht::driver = WallpaperEngine::Irrlicht::device->getVideoDriver();
+    IrrlichtContext->getDevice ()->setWindowCaption (L"Test game");
 
     // check for ps and vs support
     if (
-            WallpaperEngine::Irrlicht::driver->queryFeature (irr::video::EVDF_PIXEL_SHADER_1_1) == false &&
-            WallpaperEngine::Irrlicht::driver->queryFeature (irr::video::EVDF_ARB_FRAGMENT_PROGRAM_1) == false)
+            IrrlichtContext->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_PIXEL_SHADER_1_1) == false &&
+            IrrlichtContext->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_ARB_FRAGMENT_PROGRAM_1) == false)
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("WARNING: Pixel shaders disabled because of missing driver/hardware support");
+        IrrlichtContext->getDevice ()->getLogger ()->log ("WARNING: Pixel shaders disabled because of missing driver/hardware support");
     }
 
     if (
-            WallpaperEngine::Irrlicht::driver->queryFeature (irr::video::EVDF_VERTEX_SHADER_1_1) == false &&
-            WallpaperEngine::Irrlicht::driver->queryFeature (irr::video::EVDF_ARB_VERTEX_PROGRAM_1) == false)
+            IrrlichtContext->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_VERTEX_SHADER_1_1) == false &&
+            IrrlichtContext->getDevice ()->getVideoDriver()->queryFeature (irr::video::EVDF_ARB_VERTEX_PROGRAM_1) == false)
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("WARNING: Vertex shaders disabled because of missing driver/hardware support");
+        IrrlichtContext->getDevice ()->getLogger ()->log ("WARNING: Vertex shaders disabled because of missing driver/hardware support");
     }
 
     return 0;
@@ -71,11 +80,15 @@ int init_irrlicht()
 void preconfigure_wallpaper_engine ()
 {
     // load the assets from wallpaper engine
-    WallpaperEngine::Irrlicht::device->getFileSystem ()->addFileArchive ("assets.zip", true, false);
+    IrrlichtContext->getDevice ()->getFileSystem ()->addFileArchive ("assets.zip", true, false);
 
     // register custom loaders
-    WallpaperEngine::Irrlicht::driver->addExternalImageLoader (new WallpaperEngine::Irrlicht::CImageLoaderTex ());
-    WallpaperEngine::Irrlicht::device->getFileSystem ()->addArchiveLoader (new WallpaperEngine::Irrlicht::CArchiveLoaderPkg (WallpaperEngine::Irrlicht::device->getFileSystem ()));
+    IrrlichtContext->getDevice ()->getVideoDriver()->addExternalImageLoader (
+        new WallpaperEngine::Irrlicht::CImageLoaderTex (IrrlichtContext)
+    );
+    IrrlichtContext->getDevice ()->getFileSystem ()->addArchiveLoader (
+        new WallpaperEngine::Irrlicht::CArchiveLoaderPkg (IrrlichtContext)
+    );
 }
 
 void print_help (const char* route)
@@ -158,7 +171,7 @@ int main (int argc, char* argv[])
 
     std::cout << "Initializing irrlicht to WindowID " << WinID << std::endl;
 
-    if (init_irrlicht())
+    if (init_irrlicht ())
     {
         return 1;
     }
@@ -178,21 +191,21 @@ int main (int argc, char* argv[])
         // pkg mode
         case 1:
             path = stringPathFixes(path);
-            wallpaper_path = WallpaperEngine::Irrlicht::device->getFileSystem ()->getAbsolutePath (path.c_str ());
+            wallpaper_path = IrrlichtContext->getDevice ()->getFileSystem ()->getAbsolutePath (path.c_str ());
             project_path = wallpaper_path + "project.json";
             scene_path = wallpaper_path + "scene.pkg";
 
-            WallpaperEngine::Irrlicht::device->getFileSystem ()->addFileArchive (scene_path, true, false); // add the pkg file to the lookup list
+            IrrlichtContext->getDevice ()->getFileSystem ()->addFileArchive (scene_path, true, false); // add the pkg file to the lookup list
             break;
 
         // folder mode
         case 2:
             path = stringPathFixes(path);
-            wallpaper_path = WallpaperEngine::Irrlicht::device->getFileSystem ()->getAbsolutePath (path.c_str ());
+            wallpaper_path = IrrlichtContext->getDevice ()->getFileSystem ()->getAbsolutePath (path.c_str ());
             project_path = wallpaper_path + "project.json";
 
             // set our working directory
-            WallpaperEngine::Irrlicht::device->getFileSystem ()->changeWorkingDirectoryTo (wallpaper_path);
+            IrrlichtContext->getDevice ()->getFileSystem ()->changeWorkingDirectoryTo (wallpaper_path);
             break;
 
         default:
@@ -205,7 +218,7 @@ int main (int argc, char* argv[])
 
         if (SDL_Init (SDL_INIT_AUDIO) < 0 || mixer_flags != Mix_Init (mixer_flags))
         {
-            WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot initialize SDL audio system", irr::ELL_ERROR);
+            IrrlichtContext->getDevice ()->getLogger ()->log ("Cannot initialize SDL audio system", irr::ELL_ERROR);
             return -1;
         }
 
@@ -221,7 +234,10 @@ int main (int argc, char* argv[])
     }
     else
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("Non-orthogonal cameras not supported yet!!", irr::ELL_ERROR);
+        IrrlichtContext->getDevice ()->getLogger ()->log (
+            "Non-orthogonal cameras not supported yet!!", irr::ELL_ERROR
+        );
+
         return -2;
     }
 
@@ -232,11 +248,11 @@ int main (int argc, char* argv[])
     int32_t minimumTime = 1000 / 90;
     int32_t currentTime = 0;
 
-    while (WallpaperEngine::Irrlicht::device->run () && WallpaperEngine::Irrlicht::driver)
+    while (IrrlichtContext->getDevice ()->run () && IrrlichtContext && IrrlichtContext->getDevice ())
     {
         // if (device->isWindowActive ())
         {
-            currentTime = WallpaperEngine::Irrlicht::device->getTimer ()->getTime ();
+            currentTime = IrrlichtContext->getDevice ()->getTimer ()->getTime ();
             g_Time = currentTime / 1000.0f;
 
             if (currentTime - lastTime > minimumTime)
@@ -246,7 +262,7 @@ int main (int argc, char* argv[])
             }
             else
             {
-                WallpaperEngine::Irrlicht::device->sleep (1, false);
+                IrrlichtContext->getDevice ()->sleep (1, false);
             }
         }
     }

+ 4 - 2
src/WallpaperEngine/FileSystem/FileSystem.cpp

@@ -2,13 +2,15 @@
 #include "FileSystem.h"
 
 // engine includes
-#include "WallpaperEngine/Irrlicht/Irrlicht.h"
+#include "WallpaperEngine/Irrlicht/CContext.h"
+
+extern WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
 
 namespace WallpaperEngine::FileSystem
 {
     std::string loadFullFile (irr::io::path file)
     {
-        irr::io::IReadFile* reader = WallpaperEngine::Irrlicht::device->getFileSystem ()->createAndOpenFile (file);
+        irr::io::IReadFile* reader = IrrlichtContext->getDevice ()->getFileSystem ()->createAndOpenFile (file);
 
         if (reader == NULL)
             throw std::runtime_error ("Cannot open file " + std::string (file.c_str ()) + " for reading");

+ 14 - 0
src/WallpaperEngine/Irrlicht/CContext.cpp

@@ -0,0 +1,14 @@
+#include "CContext.h"
+
+namespace WallpaperEngine::Irrlicht
+{
+    void CContext::setDevice (irr::IrrlichtDevice* device)
+    {
+        this->m_device = device;
+    }
+
+    irr::IrrlichtDevice* CContext::getDevice ()
+    {
+        return this->m_device;
+    }
+};

+ 16 - 0
src/WallpaperEngine/Irrlicht/CContext.h

@@ -0,0 +1,16 @@
+#pragma once
+
+#include <irrlicht/irrlicht.h>
+
+namespace WallpaperEngine::Irrlicht
+{
+    class CContext
+    {
+    public:
+        void setDevice (irr::IrrlichtDevice* device);
+
+        irr::IrrlichtDevice* getDevice ();
+    private:
+        irr::IrrlichtDevice* m_device;
+    };
+};

+ 97 - 107
src/WallpaperEngine/Irrlicht/CFileList.cpp

@@ -2,145 +2,135 @@
 
 #include "CFileList.h"
 
-using namespace WallpaperEngine::Irrlicht;
-using namespace irr;
-
-static const io::path emptyFileListEntry;
-
-CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
-        : IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path)
+namespace WallpaperEngine::Irrlicht
 {
-    Path.replace('\\', '/');
-}
+    static const irr::io::path emptyFileListEntry;
 
-CFileList::~CFileList()
-{
-    Files.clear();
-}
+    CFileList::CFileList (const irr::io::path& path, bool ignoreCase, bool ignorePaths) :
+            m_ignorePaths (ignorePaths),
+            m_ignoreCase (ignoreCase),
+            m_path(path)
+    {
+        this->m_path.replace ('\\', '/');
+    }
 
-u32 CFileList::getFileCount() const
-{
-    return Files.size();
-}
+    CFileList::~CFileList ()
+    {
+        this->m_files.clear ();
+    }
 
-void CFileList::sort()
-{
-    Files.sort();
-}
+    irr::u32 CFileList::getFileCount () const
+    {
+        return this->m_files.size ();
+    }
 
-const io::path& CFileList::getFileName(u32 index) const
-{
-    if (index >= Files.size())
-        return emptyFileListEntry;
+    void CFileList::sort ()
+    {
+        this->m_files.sort ();
+    }
 
-    return Files[index].Name;
-}
+    const irr::io::path& CFileList::getFileName (irr::u32 index) const
+    {
+        return (index < this->m_files.size ()) ? this->m_files [index].Name : emptyFileListEntry;
+    }
 
 
 //! Gets the full name of a file in the list, path included, based on an index.
-const io::path& CFileList::getFullFileName(u32 index) const
-{
-    if (index >= Files.size())
-        return emptyFileListEntry;
-
-    return Files[index].FullName;
-}
-
-//! adds a file or folder
-u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id)
-{
-    SFileListEntry entry;
-    entry.ID   = id ? id : Files.size();
-    entry.Offset = offset;
-    entry.Size = size;
-    entry.Name = fullPath;
-    entry.Name.replace('\\', '/');
-    entry.IsDirectory = isDirectory;
-
-    // remove trailing slash
-    if (entry.Name.lastChar() == '/')
+    const irr::io::path& CFileList::getFullFileName (irr::u32 index) const
     {
-        entry.IsDirectory = true;
-        entry.Name[entry.Name.size()-1] = 0;
-        entry.Name.validate();
+        return (index < this->m_files.size ()) ? this->m_files [index].FullName : emptyFileListEntry;
     }
 
-    if (IgnoreCase)
-        entry.Name.make_lower();
-
-    entry.FullName = entry.Name;
-
-    core::deletePathFromFilename(entry.Name);
+//! adds a file or folder
+    irr::u32 CFileList::addItem (const irr::io::path& fullPath, irr::u32 offset, irr::u32 size, bool isDirectory, irr::u32 id)
+    {
+        SFileListEntry entry;
+        entry.ID   = id ? id : this->m_files.size ();
+        entry.Offset = offset;
+        entry.Size = size;
+        entry.Name = fullPath;
+        entry.Name.replace ('\\', '/');
+        entry.IsDirectory = isDirectory;
+
+        // remove trailing slash
+        if (entry.Name.lastChar () == '/')
+        {
+            entry.IsDirectory = true;
+            entry.Name [entry.Name.size ()-1] = 0;
+            entry.Name.validate ();
+        }
+
+        if (this->m_ignoreCase)
+            entry.Name.make_lower ();
 
-    if (IgnorePaths)
         entry.FullName = entry.Name;
 
-    //os::Printer::log(Path.c_str(), entry.FullName);
+        irr::core::deletePathFromFilename (entry.Name);
 
-    Files.push_back(entry);
+        if (this->m_ignorePaths)
+            entry.FullName = entry.Name;
 
-    return Files.size() - 1;
-}
+        this->m_files.push_back (entry);
 
-//! Returns the ID of a file in the file list, based on an index.
-u32 CFileList::getID(u32 index) const
-{
-    return index < Files.size() ? Files[index].ID : 0;
-}
+        return this->m_files.size () - 1;
+    }
 
-bool CFileList::isDirectory(u32 index) const
-{
-    bool ret = false;
-    if (index < Files.size())
-        ret = Files[index].IsDirectory;
+//! Returns the ID of a file in the file list, based on an index.
+    irr::u32 CFileList::getID (irr::u32 index) const
+    {
+        return (index < this->m_files.size ()) ? this->m_files [index].ID : 0;
+    }
 
-    return ret;
-}
+    bool CFileList::isDirectory (irr::u32 index) const
+    {
+        return (index < this->m_files.size ()) ? this->m_files [index].IsDirectory : false;
+    }
 
 //! Returns the size of a file
-u32 CFileList::getFileSize(u32 index) const
-{
-    return index < Files.size() ? Files[index].Size : 0;
-}
+    irr::u32 CFileList::getFileSize (irr::u32 index) const
+    {
+        return (index < this->m_files.size ()) ? this->m_files [index].Size : 0;
+    }
 
 //! Returns the size of a file
-u32 CFileList::getFileOffset(u32 index) const
-{
-    return index < Files.size() ? Files[index].Offset : 0;
-}
+    irr::u32 CFileList::getFileOffset (irr::u32 index) const
+    {
+        return (index < this->m_files.size ()) ? this->m_files [index].Offset : 0;
+    }
 
 
 //! Searches for a file or folder within the list, returns the index
-s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) const
-{
-    SFileListEntry entry;
-    // we only need FullName to be set for the search
-    entry.FullName = filename;
-    entry.IsDirectory = isDirectory;
+    irr::s32 CFileList::findFile (const irr::io::path& filename, bool isDirectory = false) const
+    {
+        SFileListEntry entry;
+        // we only need FullName to be set for the search
+        entry.FullName = filename;
+        entry.IsDirectory = isDirectory;
 
-    // exchange
-    entry.FullName.replace('\\', '/');
+        // exchange
+        entry.FullName.replace('\\', '/');
 
-    // remove trailing slash
-    if (entry.FullName.lastChar() == '/')
-    {
-        entry.IsDirectory = true;
-        entry.FullName[entry.FullName.size()-1] = 0;
-        entry.FullName.validate();
-    }
+        // remove trailing slash
+        if (entry.FullName.lastChar () == '/')
+        {
+            entry.IsDirectory = true;
+            entry.FullName [entry.FullName.size ()-1] = 0;
+            entry.FullName.validate ();
+        }
 
-    if (IgnoreCase)
-        entry.FullName.make_lower();
+        if (this->m_ignoreCase)
+            entry.FullName.make_lower ();
 
-    if (IgnorePaths)
-        core::deletePathFromFilename(entry.FullName);
+        if (this->m_ignorePaths)
+            irr::core::deletePathFromFilename (entry.FullName);
 
-    return Files.binary_search(entry);
-}
+        return this->m_files.binary_search (entry);
+    }
 
 
 //! Returns the base path of the file list
-const io::path& CFileList::getPath() const
-{
-    return Path;
-}
+    const irr::io::path& CFileList::getPath () const
+    {
+        return m_path;
+    }
+};

+ 27 - 29
src/WallpaperEngine/Irrlicht/CFileList.h

@@ -2,8 +2,6 @@
 
 #include <irrlicht/irrlicht.h>
 
-using namespace irr;
-
 namespace WallpaperEngine::Irrlicht
 {
     //! An entry in a list of files, can be a folder or a file.
@@ -12,49 +10,49 @@ namespace WallpaperEngine::Irrlicht
         //! The name of the file
         /** If this is a file or folder in the virtual filesystem and the archive
         was created with the ignoreCase flag then the file name will be lower case. */
-        io::path Name;
+        irr::io::path Name;
 
         //! The name of the file including the path
         /** If this is a file or folder in the virtual filesystem and the archive was
         created with the ignoreDirs flag then it will be the same as Name. */
-        io::path FullName;
+        irr::io::path FullName;
 
         //! The size of the file in bytes
-        u32 Size;
+        irr::u32 Size;
 
         //! The ID of the file in an archive
         /** This is used to link the FileList entry to extra info held about this
         file in an archive, which can hold things like data offset and CRC. */
-        u32 ID;
+        irr::u32 ID;
 
         //! FileOffset inside an archive
-        u32 Offset;
+        irr::u32 Offset;
 
         //! True if this is a folder, false if not.
         bool IsDirectory;
 
         //! The == operator is provided so that CFileList can slowly search the list!
-        bool operator ==(const struct SFileListEntry& other) const
+        bool operator == (const struct SFileListEntry& other) const
         {
             if (IsDirectory != other.IsDirectory)
                 return false;
 
-            return FullName.equals_ignore_case(other.FullName);
+            return FullName.equals_ignore_case (other.FullName);
         }
 
         //! The < operator is provided so that CFileList can sort and quickly search the list.
-        bool operator <(const struct SFileListEntry& other) const
+        bool operator < (const struct SFileListEntry& other) const
         {
             if (IsDirectory != other.IsDirectory)
                 return IsDirectory;
 
-            return FullName.lower_ignore_case(other.FullName);
+            return FullName.lower_ignore_case (other.FullName);
         }
     };
 
 
     //! Implementation of a file list
-    class CFileList : public io::IFileList
+    class CFileList : public irr::io::IFileList
     {
     public:
 
@@ -62,10 +60,10 @@ namespace WallpaperEngine::Irrlicht
 
         //! Constructor
         /** \param path The path of this file archive */
-        CFileList(const io::path& path, bool ignoreCase, bool ignorePaths);
+        CFileList (const irr::io::path& path, bool ignoreCase, bool ignorePaths);
 
         //! Destructor
-        virtual ~CFileList();
+        virtual ~CFileList ();
 
         //! Add as a file or folder to the list
         /** \param fullPath The file name including path, up to the root of the file list.
@@ -73,51 +71,51 @@ namespace WallpaperEngine::Irrlicht
         \param offset The offset where the file is stored in an archive
         \param size The size of the file in bytes.
         \param id The ID of the file in the archive which owns it */
-        virtual u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0);
+        virtual irr::u32 addItem (const irr::io::path& fullPath, irr::u32 offset, irr::u32 size, bool isDirectory, irr::u32 id=0);
 
         //! Sorts the file list. You should call this after adding any items to the file list
-        virtual void sort();
+        virtual void sort ();
 
         //! Returns the amount of files in the filelist.
-        virtual u32 getFileCount() const;
+        virtual irr::u32 getFileCount () const;
 
         //! Gets the name of a file in the list, based on an index.
-        virtual const io::path& getFileName(u32 index) const;
+        virtual const irr::io::path& getFileName (irr::u32 index) const;
 
         //! Gets the full name of a file in the list, path included, based on an index.
-        virtual const io::path& getFullFileName(u32 index) const;
+        virtual const irr::io::path& getFullFileName (irr::u32 index) const;
 
         //! Returns the ID of a file in the file list, based on an index.
-        virtual u32 getID(u32 index) const;
+        virtual irr::u32 getID (irr::u32 index) const;
 
         //! Returns true if the file is a directory
-        virtual bool isDirectory(u32 index) const;
+        virtual bool isDirectory (irr::u32 index) const;
 
         //! Returns the size of a file
-        virtual u32 getFileSize(u32 index) const;
+        virtual irr::u32 getFileSize (irr::u32 index) const;
 
         //! Returns the offest of a file
-        virtual u32 getFileOffset(u32 index) const;
+        virtual irr::u32 getFileOffset (irr::u32 index) const;
 
         //! Searches for a file or folder within the list, returns the index
-        virtual s32 findFile(const io::path& filename, bool isFolder) const;
+        virtual irr::s32 findFile (const irr::io::path& filename, bool isFolder) const;
 
         //! Returns the base path of the file list
-        virtual const io::path& getPath() const;
+        virtual const irr::io::path& getPath () const;
 
     protected:
 
         //! Ignore paths when adding or searching for files
-        bool IgnorePaths;
+        bool m_ignorePaths;
 
         //! Ignore case when adding or searching for files
-        bool IgnoreCase;
+        bool m_ignoreCase;
 
         //! Path to the file list
-        io::path Path;
+        irr::io::path m_path;
 
         //! List of files
-        core::array<SFileListEntry> Files;
+        irr::core::array<SFileListEntry> m_files;
     };
 }
 

+ 492 - 421
src/WallpaperEngine/Irrlicht/CImageLoaderTEX.cpp

@@ -2,548 +2,619 @@
 
 #include <irrlicht/irrlicht.h>
 #include <lz4.h>
-#include <WallpaperEngine/Irrlicht/Irrlicht.h>
 #include <string>
+#include <stdexcept>
 
-using namespace irr::video;
 using namespace WallpaperEngine::Irrlicht;
 
-//! returns true if the file maybe is able to be loaded by this class
-//! based on the file extension (e.g. ".tga")
-bool CImageLoaderTex::isALoadableFileExtension (const io::path &filename) const
+namespace WallpaperEngine::Irrlicht
 {
-    return core::hasFileExtension (filename, "tex");
-}
-
-
-//! returns true if the file maybe is able to be loaded by this class
-bool CImageLoaderTex::isALoadableFileFormat (io::IReadFile *file) const
-{
-    return false;
-}
-
-
-// load in the image data
-IImage *CImageLoaderTex::loadImage (io::IReadFile *input) const
-{
-    if (!input)
-        return nullptr;
-
-    video::IImage *image = nullptr;
-
-    char buffer [1024];
-
-    if (input->read (buffer, 9) != 9)
+    CImageLoaderTex::TextureMipmap::TextureMipmap ()
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: cannot read header\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-        return nullptr;
     }
 
-    if (memcmp (buffer, "TEXV0005", 9) != 0)
+    CImageLoaderTex::TextureMipmap::~TextureMipmap ()
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: not really a tex\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-        return nullptr;
-    }
+        if (this->compression == 1)
+            delete this->compressedData;
 
-    if (input->read (buffer, 9) != 9)
-    {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: cannot read second header\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-        return nullptr;
+        delete this->uncompressedData;
     }
 
-    if (memcmp (buffer, "TEXI0001", 9) != 0)
+    void CImageLoaderTex::TextureMipmap::decompressData ()
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: not really a tex\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-        return nullptr;
+        if (this->compression == 1)
+        {
+            this->uncompressedData = new char [this->uncompressedSize];
+
+            int result = LZ4_decompress_safe (
+                this->compressedData, this->uncompressedData,
+                this->compressedSize, this->uncompressedSize
+            );
+
+            if (!result)
+            {
+                throw std::runtime_error ("Cannot decompress texture data");
+            }
+        }
     }
 
-    u32 width;
-    u32 height;
-    u32 texture_width;
-    u32 texture_height;
-    u32 format;
-    u32 imageFormat = FREE_IMAGE_FORMAT::FIF_UNKNOWN;
-    u8 containerVersion = 0;
-
-    input->read (&format, 4);
-    input->seek (4, true); // ignore bytes
-    input->read (&texture_width, 4);
-    input->read (&texture_height, 4);
-    input->read (&width, 4);
-    input->read (&height, 4);
-    input->seek (4, true); // ignore bytes
-    input->read (buffer, 9);
-
-    if (memcmp (buffer, "TEXB0003", 9) == 0)
+    CImageLoaderTex::TextureContainer::TextureContainer () :
+        freeimageFormat (FREE_IMAGE_FORMAT::FIF_UNKNOWN)
     {
-        containerVersion = 3;
-        input->seek (4, true);
-        input->read (&imageFormat, 4);
     }
-    else if (memcmp (buffer, "TEXB0002", 9) == 0)
+
+    CImageLoaderTex::TextureContainer::~TextureContainer ()
     {
-        containerVersion = 2;
+        std::vector <TextureMipmap*>::const_iterator cur = this->mipmaps.begin ();
+        std::vector <TextureMipmap*>::const_iterator end = this->mipmaps.end ();
 
-        input->seek (4, true);
+        for (; cur != end; cur ++)
+        {
+            delete *cur;
+        }
     }
-    else if (memcmp (buffer, "TEXB0001", 9) == 0)
+
+    CImageLoaderTex::CImageLoaderTex (CContext* context) :
+        m_context (context)
     {
-        containerVersion = 1;
-        input->seek (4, true);
     }
-    else
+
+    //! returns true if the file maybe is able to be loaded by this class
+    //! based on the file extension (e.g. ".tga")
+    bool CImageLoaderTex::isALoadableFileExtension (const irr::io::path &filename) const
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: Unknown container type\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-        return nullptr;
+        return irr::core::hasFileExtension (filename, "tex");
     }
 
-    if (format == TextureFormat::A8)
+
+    //! returns true if the file maybe is able to be loaded by this class
+    bool CImageLoaderTex::isALoadableFileFormat (irr::io::IReadFile *file) const
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()-> log ("LOAD TEX: A8 not supported\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-        return nullptr;
+        return false;
     }
 
-    if (format == TextureFormat::RA88)
+    CImageLoaderTex::TextureContainer* CImageLoaderTex::parseHeader (irr::io::IReadFile* input) const
     {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: RA88 not supported\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-        return nullptr;
-    }
+        char buffer [1024];
 
-    u32 mipmap_count = 0;
+        if (input->read (buffer, 9) != 9 || memcmp (buffer, "TEXV0005", 9) != 0)
+        {
+            throw std::runtime_error ("unexpected container type");
+        }
 
-    input->read (&mipmap_count, 4);
+        if (input->read (buffer, 9) != 9 || memcmp (buffer, "TEXI0001", 9) != 0)
+        {
+            throw std::runtime_error ("unexpected sub-container type");
+        }
 
-    u32 mipmap_width = 0;
-    u32 mipmap_height = 0;
-    u32 mipmap_compression = 0;
-    u32 mipmap_uncompressed_size = 0;
-    u32 mipmap_compressed_size = 0;
+        TextureContainer* header = new TextureContainer;
 
-    input->read (&mipmap_width, 4);
-    input->read (&mipmap_height, 4);
+        input->read (&header->format, 4);
+        input->seek (4, true); // ignore bytes
+        input->read (&header->textureWidth, 4);
+        input->read (&header->textureHeight, 4);
+        input->read (&header->width, 4);
+        input->read (&header->height, 4);
+        input->seek (4, true); // ignore bytes
+        input->read (buffer, 9);
 
-    if (containerVersion > 1)
-    {
-        input->read (&mipmap_compression, 4);
-        input->read (&mipmap_uncompressed_size, 4);
-    }
+        if (memcmp (buffer, "TEXB0003", 9) == 0)
+        {
+            header->containerVersion = ContainerVersion::TEXB0003;
 
-    input->read (&mipmap_compressed_size, 4);
+            input->seek (4, true);
+            input->read (&header->freeimageFormat, 4);
+        }
+        else if (memcmp (buffer, "TEXB0002", 9) == 0)
+        {
+            header->containerVersion = ContainerVersion::TEXB0002;
 
-    // TODO: BETTER POSITION FOR THIS
-    if (mipmap_compression == 0)
-    {
-        // this might be better named as mipmap_bytes_size instead of compressed_size
-        // as in uncompressed files this variable actually holds the file length
-        mipmap_uncompressed_size = mipmap_compressed_size;
-    }
+            input->seek (4, true);
+        }
+        else if (memcmp (buffer, "TEXB0001", 9) == 0)
+        {
+            header->containerVersion = ContainerVersion::TEXB0001;
 
-    char *decompressedBuffer = new char [mipmap_uncompressed_size];
+            input->seek (4, true);
+        }
+        else
+        {
+            delete header;
 
-    if (mipmap_compression == 1)
-    {
-        char *compressedBuffer = new char [mipmap_compressed_size];
+            throw std::runtime_error ("Unknown container type");
+        }
 
-        input->read (compressedBuffer, mipmap_compressed_size);
+        if (header->format == TextureFormat::A8)
+        {
+            delete header;
 
-        int result = LZ4_decompress_safe (compressedBuffer, decompressedBuffer, mipmap_compressed_size, mipmap_uncompressed_size);
+            throw std::runtime_error ("A8 format not supported yet");
+        }
 
-        if (!result)
+        if (header->format == TextureFormat::RA88)
         {
-            delete [] decompressedBuffer;
-            delete [] compressedBuffer;
-            WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: cannot decompress texture data\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-            return nullptr;
+            delete header;
+
+            throw std::runtime_error ("RA88 format not supported yet");
         }
 
-        delete [] compressedBuffer;
-    }
-    else
-    {
-        input->read (decompressedBuffer, mipmap_uncompressed_size);
+        input->read (&header->mipmapCount, 4);
+
+        for (irr::u32 i = 0; i < header->mipmapCount; i ++)
+        {
+            header->mipmaps.push_back (
+                this->parseMipmap (header, input)
+            );
+        }
+
+        return header;
     }
 
-    if (imageFormat == FREE_IMAGE_FORMAT::FIF_UNKNOWN)
+    CImageLoaderTex::TextureMipmap* CImageLoaderTex::parseMipmap(TextureContainer* header, irr::io::IReadFile* input) const
     {
-        image = WallpaperEngine::Irrlicht::driver->createImage (ECF_A8R8G8B8, irr::core::dimension2d<u32> (width, height));
+        TextureMipmap* mipmap = new TextureMipmap ();
 
-        if (!image)
+        input->read (&mipmap->width, 4);
+        input->read (&mipmap->height, 4);
+
+        if (header->containerVersion == ContainerVersion::TEXB0002 ||
+            header->containerVersion == ContainerVersion::TEXB0003)
         {
-            delete [] decompressedBuffer;
-            delete image;
-            WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: cannot create destination image\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-            return nullptr;
+            input->read (&mipmap->compression, 4);
+            input->read (&mipmap->uncompressedSize, 4);
         }
 
-        switch (format)
+        input->read (&mipmap->compressedSize, 4);
+
+        // TODO: BETTER POSITION FOR THIS
+        if (mipmap->compression == 0)
         {
-            case TextureFormat::ARGB8888:
-                this->loadImageFromARGB8Data (image, decompressedBuffer, width, height, mipmap_width);
-                break;
-            case TextureFormat::DXT5:
-                this->loadImageFromDXT5 (image, decompressedBuffer, width, height, mipmap_width, mipmap_height);
-                break;
-            case TextureFormat::DXT1:
-                this->loadImageFromDXT1 (image, decompressedBuffer, width, height, mipmap_width, mipmap_height);
-                break;
-            case TextureFormat::DXT3:
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: DXT3 textures not supported yet\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-                delete [] decompressedBuffer;
-                delete image;
-                return nullptr;
+            // this might be better named as mipmap_bytes_size instead of compressed_size
+            // as in uncompressed files this variable actually holds the file length
+            mipmap->uncompressedSize = mipmap->compressedSize;
         }
+
+        mipmap->uncompressedData = new char [mipmap->uncompressedSize];
+
+        if (mipmap->compression == 1)
+        {
+            mipmap->compressedData = new char [mipmap->compressedSize];
+
+            input->read (mipmap->compressedData, mipmap->compressedSize);
+
+            mipmap->decompressData ();
+        }
+        else
+        {
+            input->read (mipmap->uncompressedData, mipmap->uncompressedSize);
+        }
+
+        return mipmap;
     }
-    else
+
+    irr::video::IImage* CImageLoaderTex::parseFile (irr::io::IReadFile* input) const
     {
-        // copy the buffer to a new address
-        char* filebuffer = new char [mipmap_uncompressed_size];
-        char tmpname [TMP_MAX];
-
-        // copy file data to the final file buffer to be used
-        memcpy (filebuffer, decompressedBuffer, mipmap_uncompressed_size);
-        // generate temporal name
-        std::tmpnam (tmpname);
-        // store it in a std::string
-        std::string filename = tmpname;
-        irr::io::IReadFile* file;
-
-        // free image format
-        switch (imageFormat)
+        irr::video::IImage *image = nullptr;
+        TextureContainer* header = nullptr;
+        TextureMipmap* mipmap = nullptr;
+
+        if (input == nullptr)
+            return nullptr;
+
+        header = this->parseHeader (input);
+        mipmap = *header->mipmaps.begin ();
+
+        if (header->freeimageFormat == FREE_IMAGE_FORMAT::FIF_UNKNOWN)
         {
-            case FREE_IMAGE_FORMAT::FIF_BMP:
-                // add extension to the file
-                filename += ".bmp";
-                file = WallpaperEngine::Irrlicht::device->getFileSystem ()->createMemoryReadFile (filebuffer, mipmap_uncompressed_size, filename.c_str (), true);
-                break;
-            case FREE_IMAGE_FORMAT::FIF_PNG:
-                // add extension to the file
-                filename += ".png";
-                file = WallpaperEngine::Irrlicht::device->getFileSystem ()->createMemoryReadFile (filebuffer, mipmap_uncompressed_size, filename.c_str (), true);
-                break;
-            case FREE_IMAGE_FORMAT::FIF_JPEG:
-                // add extension to the file
-                filename += ".jpg";
-                WallpaperEngine::Irrlicht::device->getFileSystem ()->createAndWriteFile ("/tmp/test.jpg", false)->write (filebuffer, mipmap_uncompressed_size);
-                file = WallpaperEngine::Irrlicht::device->getFileSystem ()->createMemoryReadFile (filebuffer, mipmap_uncompressed_size, filename.c_str (), true);
-                break;
-            case FREE_IMAGE_FORMAT::FIF_GIF:
-                filename += ".gif";
-                file = WallpaperEngine::Irrlicht::device->getFileSystem ()->createMemoryReadFile (filebuffer, mipmap_uncompressed_size, filename.c_str (), true);
-                break;
-            default:
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: detected unsupported free-image format\n", input->getFileName ().c_str (), irr::ELL_ERROR);
-                delete [] decompressedBuffer;
+            image = this->m_context->getDevice ()->getVideoDriver ()->createImage (
+                    irr::video::ECF_A8R8G8B8, irr::core::dimension2d<irr::u32> (header->width, header->height)
+            );
+
+            if (image == nullptr)
+            {
+                delete header;
+
+                throw std::runtime_error ("cannot create destination image");
+            }
+
+            switch (header->format)
+            {
+                case TextureFormat::ARGB8888:
+                    this->loadImageFromARGB8Data (
+                            image, mipmap->uncompressedData, header->width, header->height, mipmap->width
+                    );
+                    break;
+                case TextureFormat::DXT5:
+                    this->loadImageFromDXT5 (
+                            image, mipmap->uncompressedData, header->width, header->height, mipmap->width, mipmap->height
+                    );
+                    break;
+                case TextureFormat::DXT1:
+                    this->loadImageFromDXT1 (
+                            image, mipmap->uncompressedData, header->width, header->height, mipmap->width, mipmap->height
+                    );
+                    break;
+                case TextureFormat::DXT3:
+                    delete header;
+
+                    throw std::runtime_error ("DXT3 textures not supported yet");
+            }
+        }
+        else
+        {
+            // generate a memory file for irrlicht to load the proper one as free image files
+            // that are used by wallpaperengine are usually supported formats in irrlicht
+            // TODO: FIND A WAY TO CALL THE PROPER LOADER DIRECTLY INSTEAD OF GENERATING A FILE?
+            char tmpname [TMP_MAX];
+
+            std::tmpnam (tmpname);
+            std::string filename = tmpname;
+            irr::io::IReadFile* file = nullptr;
+
+            switch (header->freeimageFormat)
+            {
+                case FREE_IMAGE_FORMAT::FIF_BMP:
+                    filename += ".bmp";
+                    break;
+                case FREE_IMAGE_FORMAT::FIF_PNG:
+                    filename += ".png";
+                    break;
+                case FREE_IMAGE_FORMAT::FIF_JPEG:
+                    filename += ".jpg";
+                    break;
+                case FREE_IMAGE_FORMAT::FIF_GIF:
+                    filename += ".gif";
+                    break;
+                default:
+                    throw std::runtime_error ("Unsupported free image extension");
+            }
+
+            // create a copy of the file information for the filesystem module of irrlicht
+            // this will be freed automatically by irrlicht so we can freely delete the container
+            // data from memory without leaking memory
+            char* filebuffer = new char [mipmap->uncompressedSize];
+
+            memcpy (filebuffer, mipmap->uncompressedData, mipmap->uncompressedSize);
+
+            file = this->m_context->getDevice ()->getFileSystem ()->createMemoryReadFile (
+                    filebuffer, mipmap->uncompressedSize, filename.c_str (), true
+            );
+
+            if (file == nullptr)
+            {
                 delete [] filebuffer;
-                return nullptr;
+                delete header;
+
+                throw std::runtime_error ("cannot create temporal memory file");
+            }
+
+            image = this->m_context->getDevice ()->getVideoDriver ()->createImageFromFile (file);
+
+            if (image == nullptr)
+            {
+                // this takes care of freeing filebuffer
+                file->drop ();
+
+                delete header;
+
+                throw std::runtime_error ("cannot create destination image");
+            }
         }
 
-        image = WallpaperEngine::Irrlicht::driver->createImageFromFile (file);
+        // delete container info as it's not needed anymore
+        delete header;
 
-        if (!image)
+        return image;
+    }
+
+    // load in the image data
+    irr::video::IImage *CImageLoaderTex::loadImage (irr::io::IReadFile *input) const
+    {
+        try
         {
-            file->drop ();
+            return this->parseFile (input);
+        }
+        catch (std::runtime_error ex)
+        {
+            this->m_context->getDevice ()->getLogger ()->log (
+                ex.what (), input->getFileName ().c_str (), irr::ELL_ERROR
+            );
 
-            delete [] decompressedBuffer;
-            delete image;
-            WallpaperEngine::Irrlicht::device->getLogger ()->log ("LOAD TEX: cannot create destination image\n", input->getFileName ().c_str (), irr::ELL_ERROR);
             return nullptr;
         }
     }
 
-    delete [] decompressedBuffer;
-
-    return image;
-}
-
-void CImageLoaderTex::loadImageFromARGB8Data (IImage* output, const char* input, u32 width, u32 height, u32 mipmap_width) const
-{
-    u32 bytesPerPixel = output->getBytesPerPixel ();
-    char *imagedata = (char *) output->lock ();
-
-    for (u32 y = 0; y < height; y ++)
+    void CImageLoaderTex::loadImageFromARGB8Data (irr::video::IImage* output, const char* input, irr::u32 width, irr::u32 height, irr::u32 mipmap_width) const
     {
-        u32 baseDestination = y * output->getPitch ();
-        u32 baseOrigin = y * (mipmap_width * 4);
+        irr::u32 bytesPerPixel = output->getBytesPerPixel ();
+        char *imagedata = (char *) output->lock ();
 
-        for (u32 x = 0; x < width; x ++)
+        for (irr::u32 y = 0; y < height; y ++)
         {
-            imagedata [baseDestination + (x * bytesPerPixel) + 2] = input [baseOrigin + ((width - x) * 4) + 0]; // r
-            imagedata [baseDestination + (x * bytesPerPixel) + 1] = input [baseOrigin + ((width - x) * 4) + 1]; // g
-            imagedata [baseDestination + (x * bytesPerPixel) + 0] = input [baseOrigin + ((width - x) * 4) + 2]; // b
-            imagedata [baseDestination + (x * bytesPerPixel) + 3] = input [baseOrigin + ((width - x) * 4) + 3]; // alpha
+            irr::u32 baseDestination = y * output->getPitch ();
+            irr::u32 baseOrigin = y * (mipmap_width * 4);
+
+            for (irr::u32 x = 0; x < width; x ++)
+            {
+                imagedata [baseDestination + (x * bytesPerPixel) + 2] = input [baseOrigin + ((width - x) * 4) + 0]; // r
+                imagedata [baseDestination + (x * bytesPerPixel) + 1] = input [baseOrigin + ((width - x) * 4) + 1]; // g
+                imagedata [baseDestination + (x * bytesPerPixel) + 0] = input [baseOrigin + ((width - x) * 4) + 2]; // b
+                imagedata [baseDestination + (x * bytesPerPixel) + 3] = input [baseOrigin + ((width - x) * 4) + 3]; // alpha
+            }
         }
+
+        output->unlock ();
     }
 
-    output->unlock ();
-}
+    void CImageLoaderTex::loadImageFromDXT1 (irr::video::IImage* output, const char* input, irr::u32 destination_width, irr::u32 destination_height, irr::u32 origin_width, irr::u32 origin_height) const
+    {
+        char* decompressedBuffer = new char [origin_width * origin_height * 4];
 
-void CImageLoaderTex::loadImageFromDXT1 (IImage* output, const char* input, u32 destination_width, u32 destination_height, u32 origin_width, u32 origin_height) const
-{
-    char* decompressedBuffer = new char [origin_width * origin_height * 4];
+        this->BlockDecompressImageDXT1 (origin_width, origin_height, (const unsigned char*) input, (unsigned long*) decompressedBuffer);
+        this->loadImageFromARGB8Data (output, decompressedBuffer, destination_width, destination_height, origin_width);
 
-    this->BlockDecompressImageDXT1 (origin_width, origin_height, (const unsigned char*) input, (unsigned long*) decompressedBuffer);
-    this->loadImageFromARGB8Data (output, decompressedBuffer, destination_width, destination_height, origin_width);
+        delete [] decompressedBuffer;
+    }
 
-    delete [] decompressedBuffer;
-}
+    void CImageLoaderTex::loadImageFromDXT5 (irr::video::IImage* output, const char* input, irr::u32 destination_width, irr::u32 destination_height, irr::u32 origin_width, irr::u32 origin_height) const
+    {
+        char* decompressedBuffer = new char [origin_width * origin_height * 4];
 
-void CImageLoaderTex::loadImageFromDXT5 (IImage* output, const char* input, u32 destination_width, u32 destination_height, u32 origin_width, u32 origin_height) const
-{
-    char* decompressedBuffer = new char [origin_width * origin_height * 4];
+        this->BlockDecompressImageDXT5 (origin_width, origin_height, (const unsigned char*) input, (unsigned long*) decompressedBuffer);
+        this->loadImageFromARGB8Data (output, decompressedBuffer, destination_width, destination_height, origin_width);
 
-    this->BlockDecompressImageDXT5 (origin_width, origin_height, (const unsigned char*) input, (unsigned long*) decompressedBuffer);
-    this->loadImageFromARGB8Data (output, decompressedBuffer, destination_width, destination_height, origin_width);
+        delete [] decompressedBuffer;
+    }
 
-    delete [] decompressedBuffer;
-}
+    // ------------------------------------------------------------------------------------
+    // The following code is a slightly modified version of this repository
+    // https://github.com/Benjamin-Dobell/s3tc-dxt-decompression
+    // ------------------------------------------------------------------------------------
 
-// ------------------------------------------------------------------------------------
-// The following code is a slightly modified version of this repository
-// https://github.com/Benjamin-Dobell/s3tc-dxt-decompression
-// ------------------------------------------------------------------------------------
+    // unsigned long PackRGBA(): Helper method that packs RGBA channels into a single 4 byte pixel.
+    //
+    // unsigned char r:		red channel.
+    // unsigned char g:		green channel.
+    // unsigned char b:		blue channel.
+    // unsigned char a:		alpha channel.
 
-// unsigned long PackRGBA(): Helper method that packs RGBA channels into a single 4 byte pixel.
-//
-// unsigned char r:		red channel.
-// unsigned char g:		green channel.
-// unsigned char b:		blue channel.
-// unsigned char a:		alpha channel.
+    unsigned long CImageLoaderTex::PackRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const
+    {
+        return ((r << 24) | (g << 16) | (b << 8) | a);
+    }
 
-unsigned long CImageLoaderTex::PackRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const
-{
-    return ((r << 24) | (g << 16) | (b << 8) | a);
-}
-
-// void DecompressBlockDXT1(): Decompresses one block of a DXT1 texture and stores the resulting pixels at the appropriate offset in 'image'.
-//
-// unsigned long x:						x-coordinate of the first pixel in the block.
-// unsigned long y:						y-coordinate of the first pixel in the block.
-// unsigned long width: 				width of the texture being decompressed.
-// unsigned long height:				height of the texture being decompressed.
-// const unsigned char *blockStorage:	pointer to the block to decompress.
-// unsigned long *image:				pointer to image where the decompressed pixel data should be stored.
-
-void CImageLoaderTex::DecompressBlockDXT1(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const
-{
-    unsigned short color0 = *reinterpret_cast<const unsigned short *>(blockStorage);
-    unsigned short color1 = *reinterpret_cast<const unsigned short *>(blockStorage + 2);
+    // void DecompressBlockDXT1(): Decompresses one block of a DXT1 texture and stores the resulting pixels at the appropriate offset in 'image'.
+    //
+    // unsigned long x:						x-coordinate of the first pixel in the block.
+    // unsigned long y:						y-coordinate of the first pixel in the block.
+    // unsigned long width: 				width of the texture being decompressed.
+    // unsigned long height:				height of the texture being decompressed.
+    // const unsigned char *blockStorage:	pointer to the block to decompress.
+    // unsigned long *image:				pointer to image where the decompressed pixel data should be stored.
 
-    unsigned long temp;
+    void CImageLoaderTex::DecompressBlockDXT1(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const
+    {
+        unsigned short color0 = *reinterpret_cast<const unsigned short *>(blockStorage);
+        unsigned short color1 = *reinterpret_cast<const unsigned short *>(blockStorage + 2);
 
-    temp = (color0 >> 11) * 255 + 16;
-    unsigned char r0 = (unsigned char)((temp/32 + temp)/32);
-    temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
-    unsigned char g0 = (unsigned char)((temp/64 + temp)/64);
-    temp = (color0 & 0x001F) * 255 + 16;
-    unsigned char b0 = (unsigned char)((temp/32 + temp)/32);
+        unsigned long temp;
 
-    temp = (color1 >> 11) * 255 + 16;
-    unsigned char r1 = (unsigned char)((temp/32 + temp)/32);
-    temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
-    unsigned char g1 = (unsigned char)((temp/64 + temp)/64);
-    temp = (color1 & 0x001F) * 255 + 16;
-    unsigned char b1 = (unsigned char)((temp/32 + temp)/32);
+        temp = (color0 >> 11) * 255 + 16;
+        unsigned char r0 = (unsigned char)((temp/32 + temp)/32);
+        temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
+        unsigned char g0 = (unsigned char)((temp/64 + temp)/64);
+        temp = (color0 & 0x001F) * 255 + 16;
+        unsigned char b0 = (unsigned char)((temp/32 + temp)/32);
 
-    unsigned long code = *reinterpret_cast<const unsigned long *>(blockStorage + 4);
+        temp = (color1 >> 11) * 255 + 16;
+        unsigned char r1 = (unsigned char)((temp/32 + temp)/32);
+        temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
+        unsigned char g1 = (unsigned char)((temp/64 + temp)/64);
+        temp = (color1 & 0x001F) * 255 + 16;
+        unsigned char b1 = (unsigned char)((temp/32 + temp)/32);
 
-    for (int j=0; j < 4; j++)
-    {
-        for (int i=0; i < 4; i++)
-        {
-            unsigned long finalColor = 0;
-            unsigned char positionCode = (code >>  2*(4*j+i)) & 0x03;
+        unsigned long code = *reinterpret_cast<const unsigned long *>(blockStorage + 4);
 
-            if (color0 > color1)
+        for (int j=0; j < 4; j++)
+        {
+            for (int i=0; i < 4; i++)
             {
-                switch (positionCode)
+                unsigned long finalColor = 0;
+                unsigned char positionCode = (code >>  2*(4*j+i)) & 0x03;
+
+                if (color0 > color1)
                 {
-                    case 0:
-                        finalColor = PackRGBA(r0, g0, b0, 255);
-                        break;
-                    case 1:
-                        finalColor = PackRGBA(r1, g1, b1, 255);
-                        break;
-                    case 2:
-                        finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, 255);
-                        break;
-                    case 3:
-                        finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, 255);
-                        break;
+                    switch (positionCode)
+                    {
+                        case 0:
+                            finalColor = PackRGBA(r0, g0, b0, 255);
+                            break;
+                        case 1:
+                            finalColor = PackRGBA(r1, g1, b1, 255);
+                            break;
+                        case 2:
+                            finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, 255);
+                            break;
+                        case 3:
+                            finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, 255);
+                            break;
+                    }
                 }
-            }
-            else
-            {
-                switch (positionCode)
+                else
                 {
-                    case 0:
-                        finalColor = PackRGBA(r0, g0, b0, 255);
-                        break;
-                    case 1:
-                        finalColor = PackRGBA(r1, g1, b1, 255);
-                        break;
-                    case 2:
-                        finalColor = PackRGBA((r0+r1)/2, (g0+g1)/2, (b0+b1)/2, 255);
-                        break;
-                    case 3:
-                        finalColor = PackRGBA(0, 0, 0, 255);
-                        break;
+                    switch (positionCode)
+                    {
+                        case 0:
+                            finalColor = PackRGBA(r0, g0, b0, 255);
+                            break;
+                        case 1:
+                            finalColor = PackRGBA(r1, g1, b1, 255);
+                            break;
+                        case 2:
+                            finalColor = PackRGBA((r0+r1)/2, (g0+g1)/2, (b0+b1)/2, 255);
+                            break;
+                        case 3:
+                            finalColor = PackRGBA(0, 0, 0, 255);
+                            break;
+                    }
                 }
-            }
 
-            if (x + i < width)
-                image[(y + j)*width + (x + i)] = finalColor;
+                if (x + i < width)
+                    image[(y + j)*width + (x + i)] = finalColor;
+            }
         }
     }
-}
-
-// void BlockDecompressImageDXT1(): Decompresses all the blocks of a DXT1 compressed texture and stores the resulting pixels in 'image'.
-//
-// unsigned long width:					Texture width.
-// unsigned long height:				Texture height.
-// const unsigned char *blockStorage:	pointer to compressed DXT1 blocks.
-// unsigned long *image:				pointer to the image where the decompressed pixels will be stored.
 
-void CImageLoaderTex::BlockDecompressImageDXT1(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const
-{
-    unsigned long blockCountX = (width + 3) / 4;
-    unsigned long blockCountY = (height + 3) / 4;
-    unsigned long blockWidth = (width < 4) ? width : 4;
-    unsigned long blockHeight = (height < 4) ? height : 4;
+    // void BlockDecompressImageDXT1(): Decompresses all the blocks of a DXT1 compressed texture and stores the resulting pixels in 'image'.
+    //
+    // unsigned long width:					Texture width.
+    // unsigned long height:				Texture height.
+    // const unsigned char *blockStorage:	pointer to compressed DXT1 blocks.
+    // unsigned long *image:				pointer to the image where the decompressed pixels will be stored.
 
-    for (unsigned long j = 0; j < blockCountY; j++)
+    void CImageLoaderTex::BlockDecompressImageDXT1(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const
     {
-        for (unsigned long i = 0; i < blockCountX; i++) DecompressBlockDXT1(i*4, j*4, width, blockStorage + i * 8, image);
-        blockStorage += blockCountX * 8;
+        unsigned long blockCountX = (width + 3) / 4;
+        unsigned long blockCountY = (height + 3) / 4;
+        unsigned long blockWidth = (width < 4) ? width : 4;
+        unsigned long blockHeight = (height < 4) ? height : 4;
+
+        for (unsigned long j = 0; j < blockCountY; j++)
+        {
+            for (unsigned long i = 0; i < blockCountX; i++) DecompressBlockDXT1(i*4, j*4, width, blockStorage + i * 8, image);
+            blockStorage += blockCountX * 8;
+        }
     }
-}
-
-// void DecompressBlockDXT5(): Decompresses one block of a DXT5 texture and stores the resulting pixels at the appropriate offset in 'image'.
-//
-// unsigned long x:						x-coordinate of the first pixel in the block.
-// unsigned long y:						y-coordinate of the first pixel in the block.
-// unsigned long width: 				width of the texture being decompressed.
-// unsigned long height:				height of the texture being decompressed.
-// const unsigned char *blockStorage:	pointer to the block to decompress.
-// unsigned long *image:				pointer to image where the decompressed pixel data should be stored.
-
-void CImageLoaderTex::DecompressBlockDXT5(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const
-{
-    unsigned char alpha0 = *reinterpret_cast<const unsigned char *>(blockStorage);
-    unsigned char alpha1 = *reinterpret_cast<const unsigned char *>(blockStorage + 1);
 
-    const unsigned char *bits = blockStorage + 2;
-    unsigned long alphaCode1 = bits[2] | (bits[3] << 8) | (bits[4] << 16) | (bits[5] << 24);
-    unsigned short alphaCode2 = bits[0] | (bits[1] << 8);
+    // void DecompressBlockDXT5(): Decompresses one block of a DXT5 texture and stores the resulting pixels at the appropriate offset in 'image'.
+    //
+    // unsigned long x:						x-coordinate of the first pixel in the block.
+    // unsigned long y:						y-coordinate of the first pixel in the block.
+    // unsigned long width: 				width of the texture being decompressed.
+    // unsigned long height:				height of the texture being decompressed.
+    // const unsigned char *blockStorage:	pointer to the block to decompress.
+    // unsigned long *image:				pointer to image where the decompressed pixel data should be stored.
 
-    unsigned short color0 = *reinterpret_cast<const unsigned short *>(blockStorage + 8);
-    unsigned short color1 = *reinterpret_cast<const unsigned short *>(blockStorage + 10);
+    void CImageLoaderTex::DecompressBlockDXT5(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const
+    {
+        unsigned char alpha0 = *reinterpret_cast<const unsigned char *>(blockStorage);
+        unsigned char alpha1 = *reinterpret_cast<const unsigned char *>(blockStorage + 1);
 
-    unsigned long temp;
+        const unsigned char *bits = blockStorage + 2;
+        unsigned long alphaCode1 = bits[2] | (bits[3] << 8) | (bits[4] << 16) | (bits[5] << 24);
+        unsigned short alphaCode2 = bits[0] | (bits[1] << 8);
 
-    temp = (color0 >> 11) * 255 + 16;
-    unsigned char r0 = (unsigned char)((temp/32 + temp)/32);
-    temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
-    unsigned char g0 = (unsigned char)((temp/64 + temp)/64);
-    temp = (color0 & 0x001F) * 255 + 16;
-    unsigned char b0 = (unsigned char)((temp/32 + temp)/32);
+        unsigned short color0 = *reinterpret_cast<const unsigned short *>(blockStorage + 8);
+        unsigned short color1 = *reinterpret_cast<const unsigned short *>(blockStorage + 10);
 
-    temp = (color1 >> 11) * 255 + 16;
-    unsigned char r1 = (unsigned char)((temp/32 + temp)/32);
-    temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
-    unsigned char g1 = (unsigned char)((temp/64 + temp)/64);
-    temp = (color1 & 0x001F) * 255 + 16;
-    unsigned char b1 = (unsigned char)((temp/32 + temp)/32);
+        unsigned long temp;
 
-    unsigned long code = *reinterpret_cast<const unsigned long *>(blockStorage + 12);
+        temp = (color0 >> 11) * 255 + 16;
+        unsigned char r0 = (unsigned char)((temp/32 + temp)/32);
+        temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
+        unsigned char g0 = (unsigned char)((temp/64 + temp)/64);
+        temp = (color0 & 0x001F) * 255 + 16;
+        unsigned char b0 = (unsigned char)((temp/32 + temp)/32);
 
-    for (int j=0; j < 4; j++)
-    {
-        for (int i=0; i < 4; i++)
-        {
-            int alphaCodeIndex = 3*(4*j+i);
-            int alphaCode;
+        temp = (color1 >> 11) * 255 + 16;
+        unsigned char r1 = (unsigned char)((temp/32 + temp)/32);
+        temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
+        unsigned char g1 = (unsigned char)((temp/64 + temp)/64);
+        temp = (color1 & 0x001F) * 255 + 16;
+        unsigned char b1 = (unsigned char)((temp/32 + temp)/32);
 
-            if (alphaCodeIndex <= 12)
-            {
-                alphaCode = (alphaCode2 >> alphaCodeIndex) & 0x07;
-            }
-            else if (alphaCodeIndex == 15)
-            {
-                alphaCode = (alphaCode2 >> 15) | ((alphaCode1 << 1) & 0x06);
-            }
-            else // alphaCodeIndex >= 18 && alphaCodeIndex <= 45
-            {
-                alphaCode = (alphaCode1 >> (alphaCodeIndex - 16)) & 0x07;
-            }
+        unsigned long code = *reinterpret_cast<const unsigned long *>(blockStorage + 12);
 
-            unsigned char finalAlpha;
-            if (alphaCode == 0)
-            {
-                finalAlpha = alpha0;
-            }
-            else if (alphaCode == 1)
-            {
-                finalAlpha = alpha1;
-            }
-            else
+        for (int j=0; j < 4; j++)
+        {
+            for (int i=0; i < 4; i++)
             {
-                if (alpha0 > alpha1)
+                int alphaCodeIndex = 3*(4*j+i);
+                int alphaCode;
+
+                if (alphaCodeIndex <= 12)
+                {
+                    alphaCode = (alphaCode2 >> alphaCodeIndex) & 0x07;
+                }
+                else if (alphaCodeIndex == 15)
+                {
+                    alphaCode = (alphaCode2 >> 15) | ((alphaCode1 << 1) & 0x06);
+                }
+                else // alphaCodeIndex >= 18 && alphaCodeIndex <= 45
+                {
+                    alphaCode = (alphaCode1 >> (alphaCodeIndex - 16)) & 0x07;
+                }
+
+                unsigned char finalAlpha;
+                if (alphaCode == 0)
                 {
-                    finalAlpha = ((8-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/7;
+                    finalAlpha = alpha0;
+                }
+                else if (alphaCode == 1)
+                {
+                    finalAlpha = alpha1;
                 }
                 else
                 {
-                    if (alphaCode == 6)
-                        finalAlpha = 0;
-                    else if (alphaCode == 7)
-                        finalAlpha = 255;
+                    if (alpha0 > alpha1)
+                    {
+                        finalAlpha = ((8-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/7;
+                    }
                     else
-                        finalAlpha = ((6-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/5;
+                    {
+                        if (alphaCode == 6)
+                            finalAlpha = 0;
+                        else if (alphaCode == 7)
+                            finalAlpha = 255;
+                        else
+                            finalAlpha = ((6-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/5;
+                    }
                 }
-            }
 
-            unsigned char colorCode = (code >> 2*(4*j+i)) & 0x03;
+                unsigned char colorCode = (code >> 2*(4*j+i)) & 0x03;
 
-            unsigned long finalColor;
-            switch (colorCode)
-            {
-                case 0:
-                    finalColor = PackRGBA(r0, g0, b0, finalAlpha);
-                    break;
-                case 1:
-                    finalColor = PackRGBA(r1, g1, b1, finalAlpha);
-                    break;
-                case 2:
-                    finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, finalAlpha);
-                    break;
-                case 3:
-                    finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, finalAlpha);
-                    break;
-            }
+                unsigned long finalColor;
+                switch (colorCode)
+                {
+                    case 0:
+                        finalColor = PackRGBA(r0, g0, b0, finalAlpha);
+                        break;
+                    case 1:
+                        finalColor = PackRGBA(r1, g1, b1, finalAlpha);
+                        break;
+                    case 2:
+                        finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, finalAlpha);
+                        break;
+                    case 3:
+                        finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, finalAlpha);
+                        break;
+                }
 
-            if (x + i < width)
-                image[(y + j)*width + (x + i)] = finalColor;
+                if (x + i < width)
+                    image[(y + j)*width + (x + i)] = finalColor;
+            }
         }
     }
-}
-
-// void BlockDecompressImageDXT5(): Decompresses all the blocks of a DXT5 compressed texture and stores the resulting pixels in 'image'.
-//
-// unsigned long width:					Texture width.
-// unsigned long height:				Texture height.
-// const unsigned char *blockStorage:	pointer to compressed DXT5 blocks.
-// unsigned long *image:				pointer to the image where the decompressed pixels will be stored.
 
-void CImageLoaderTex::BlockDecompressImageDXT5(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const
-{
-    unsigned long blockCountX = (width + 3) / 4;
-    unsigned long blockCountY = (height + 3) / 4;
-    unsigned long blockWidth = (width < 4) ? width : 4;
-    unsigned long blockHeight = (height < 4) ? height : 4;
+    // void BlockDecompressImageDXT5(): Decompresses all the blocks of a DXT5 compressed texture and stores the resulting pixels in 'image'.
+    //
+    // unsigned long width:					Texture width.
+    // unsigned long height:				Texture height.
+    // const unsigned char *blockStorage:	pointer to compressed DXT5 blocks.
+    // unsigned long *image:				pointer to the image where the decompressed pixels will be stored.
 
-    for (unsigned long j = 0; j < blockCountY; j++)
+    void CImageLoaderTex::BlockDecompressImageDXT5(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const
     {
-        for (unsigned long i = 0; i < blockCountX; i++) DecompressBlockDXT5(i*4, j*4, width, blockStorage + i * 16, image);
-        blockStorage += blockCountX * 16;
+        unsigned long blockCountX = (width + 3) / 4;
+        unsigned long blockCountY = (height + 3) / 4;
+        unsigned long blockWidth = (width < 4) ? width : 4;
+        unsigned long blockHeight = (height < 4) ? height : 4;
+
+        for (unsigned long j = 0; j < blockCountY; j++)
+        {
+            for (unsigned long i = 0; i < blockCountX; i++) DecompressBlockDXT5(i*4, j*4, width, blockStorage + i * 16, image);
+            blockStorage += blockCountX * 16;
+        }
     }
-}
+};

+ 100 - 10
src/WallpaperEngine/Irrlicht/CImageLoaderTEX.h

@@ -1,33 +1,123 @@
 #pragma once
 
-#include <irrlicht/irrlicht.h>
+#include <vector>
 
-using namespace irr;
-using namespace irr::video;
+#include <irrlicht/irrlicht.h>
+#include "CContext.h"
 
 namespace WallpaperEngine::Irrlicht
 {
     //!  Surface Loader for PNG files
-    class CImageLoaderTex : public IImageLoader
+    class CImageLoaderTex : public irr::video::IImageLoader
     {
     public:
+        CImageLoaderTex (CContext* context);
 
         //! returns true if the file maybe is able to be loaded by this class
         //! based on the file extension (e.g. ".png")
-        virtual bool isALoadableFileExtension(const io::path& filename) const;
+        virtual bool isALoadableFileExtension(const irr::io::path& filename) const;
 
         //! returns true if the file maybe is able to be loaded by this class
-        virtual bool isALoadableFileFormat(io::IReadFile* file) const;
+        virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const;
 
         //! creates a surface from the file
-        virtual IImage* loadImage(io::IReadFile* input) const;
+        virtual irr::video::IImage* loadImage(irr::io::IReadFile* input) const;
 
-        virtual void loadImageFromARGB8Data (IImage* output, const char* input, u32 width, u32 height, u32 mipmap_width) const;
+        virtual void loadImageFromARGB8Data (irr::video::IImage* output, const char* input, irr::u32 width, irr::u32 height, irr::u32 mipmap_width) const;
 
-        virtual void loadImageFromDXT1 (IImage* output, const char* input, u32 destination_width, u32 destination_height, u32 origin_width, u32 origin_height) const;
-        virtual void loadImageFromDXT5 (IImage* output, const char* input, u32 destination_width, u32 destination_height, u32 origin_width, u32 origin_height) const;
+        virtual void loadImageFromDXT1 (irr::video::IImage* output, const char* input, irr::u32 destination_width, irr::u32 destination_height, irr::u32 origin_width, irr::u32 origin_height) const;
+        virtual void loadImageFromDXT5 (irr::video::IImage* output, const char* input, irr::u32 destination_width, irr::u32 destination_height, irr::u32 origin_width, irr::u32 origin_height) const;
 
     private:
+        enum ContainerVersion
+        {
+            UNKNOWN = -1,
+            TEXB0003 = 3,
+            TEXB0002 = 2,
+            TEXB0001 = 1
+        };
+
+        class TextureMipmap
+        {
+        public:
+            TextureMipmap ();
+            ~TextureMipmap ();
+
+            /** Width of the mipmap */
+            irr::u32 width;
+            /** Height of the mipmap */
+            irr::u32 height;
+            /** If the mipmap data is compressed */
+            irr::u32 compression;
+            /** Uncompressed size of the mipmap */
+            irr::u32 uncompressedSize;
+            /** Compress size of the mipmap */
+            irr::u32 compressedSize;
+            /** Pointer to the compressed data */
+            char* compressedData = nullptr;
+            /** Pointer to the uncompressed data */
+            char* uncompressedData = nullptr;
+            /**
+             * Performs actual decompression of the compressed data
+             */
+            void decompressData ();
+        };
+
+        class TextureContainer
+        {
+        public:
+            TextureContainer ();
+            ~TextureContainer ();
+
+            /** The version of the texture container */
+            ContainerVersion containerVersion = ContainerVersion::UNKNOWN;
+            /** Real width of the texture */
+            irr::u32 width;
+            /** Real height of the texture */
+            irr::u32 height;
+            /** Texture width in memory (power of 2) */
+            irr::u32 textureWidth;
+            /** Texture height in memory (power of 2) */
+            irr::u32 textureHeight;
+            /** Texture data format */
+            irr::u32 format;
+            /** Free Image format */
+            irr::u32 freeimageFormat;
+            /** Number of mipmap levels for the texture */
+            irr::u32 mipmapCount;
+            /** List of mipmaps */
+            std::vector <TextureMipmap*> mipmaps;
+        };
+
+        /** Irrlicht context */
+        CContext* m_context;
+
+        /**
+         * Parses the container file and returns a texture ready to be used
+         *
+         * @param input The file to parse the data from
+         *
+         * @return The texture ready to be used
+         */
+        irr::video::IImage* parseFile (irr::io::IReadFile* input) const;
+        /**
+         * Parses the container header and returns it's information
+         *
+         * @param input The file to parse the data from
+         *
+         * @return The container header data
+         */
+        TextureContainer* parseHeader (irr::io::IReadFile* input) const;
+        /**
+         * Parses a mipmap level and returns it's information
+         *
+         * @param header The container header where this mipmap is contained
+         * @param input The file to parse the data from
+         *
+         * @return The mipmap info ready
+         */
+        TextureMipmap* parseMipmap (TextureContainer* header, irr::io::IReadFile* input) const;
+
         void BlockDecompressImageDXT1(unsigned long width, unsigned long height, const unsigned char *blockStorage, unsigned long *image) const;
         void DecompressBlockDXT1(unsigned long x, unsigned long y, unsigned long width, const unsigned char *blockStorage, unsigned long *image) const;
         unsigned long PackRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const;

+ 122 - 134
src/WallpaperEngine/Irrlicht/CPkgReader.cpp

@@ -1,192 +1,180 @@
-#include <WallpaperEngine/Irrlicht/Irrlicht.h>
 #include "CPkgReader.h"
 
-using namespace WallpaperEngine::Irrlicht;
-
-CArchiveLoaderPkg::CArchiveLoaderPkg(irr::io::IFileSystem* fs)
-        : FileSystem(fs)
+namespace WallpaperEngine::Irrlicht
 {
+
+    CArchiveLoaderPkg::CArchiveLoaderPkg (CContext* context) :
+            m_context (context)
+    {
 #ifdef _DEBUG
-    setDebugName("CArchiveLoaderWAD");
+        setDebugName("CArchiveLoaderWAD");
 #endif
-}
-
+    }
 
-//! returns true if the file maybe is able to be loaded by this class
-bool CArchiveLoaderPkg::isALoadableFileFormat(const irr::io::path& filename) const
-{
-    return irr::core::hasFileExtension (filename, "pkg");
-}
+    bool CArchiveLoaderPkg::isALoadableFileFormat(const irr::io::path& filename) const
+    {
+        return irr::core::hasFileExtension (filename, "pkg");
+    }
 
+    irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(const irr::io::path& filename, bool ignoreCase, bool ignorePaths) const
+    {
+        irr::io::IFileArchive *archive = nullptr;
+        irr::io::IReadFile* file = this->m_context->getDevice ()->getFileSystem ()->createAndOpenFile(filename);
 
-//! Creates an archive from the filename
-/** \param file File handle to check.
-\return Pointer to newly created archive, or 0 upon error. */
-irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(const irr::io::path& filename, bool ignoreCase, bool ignorePaths) const
-{
-    irr::io::IFileArchive *archive = nullptr;
-    irr::io::IReadFile* file = FileSystem->createAndOpenFile(filename);
+        if (file)
+        {
+            archive = this->createArchive (file, ignoreCase, ignorePaths);
+            file->drop ();
+        }
 
-    if (file)
-    {
-        archive = createArchive (file, ignoreCase, ignorePaths);
-        file->drop ();
+        return archive;
     }
 
-    return archive;
-}
+    irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths) const
+    {
+        irr::io::IFileArchive *archive = nullptr;
 
-//! creates/loads an archive from the file.
-//! \return Pointer to the created archive. Returns 0 if loading failed.
-irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths) const
-{
-    irr::io::IFileArchive *archive = nullptr;
+        if (file)
+        {
+            file->seek (0);
+            archive = new CPkgReader (file, ignoreCase, ignorePaths);
+        }
 
-    if (file)
-    {
-        file->seek (0);
-        archive = new CPkgReader (file, ignoreCase, ignorePaths);
+        return archive;
     }
 
-    return archive;
-}
+    bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::IReadFile* file) const
+    {
+        unsigned int size;
+        char* pointer;
 
+        file->read (&size, 4);
 
-//! Check if the file might be loaded by this class
-/** Check might look into the file.
-\param file File handle to check.
-\return True if file seems to be loadable. */
-bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::IReadFile* file) const
-{
-    unsigned int size;
-    char* pointer;
+        // the string doesnt include the null terminator
+        size ++;
 
-    file->read (&size, 4);
+        pointer = new char [size];
+        memset (pointer, 0, size);
 
-    // the string doesnt include the null terminator
-    size ++;
+        file->read (pointer, size - 1);
 
-    pointer = new char [size];
-    memset (pointer, 0, size);
+        if (strcmp (pointer, "PKGV0002") != 0 && strcmp (pointer, "PKGV0001") != 0)
+        {
+            delete [] pointer;
+            return false;
+        }
 
-    file->read (pointer, size - 1);
+        delete [] pointer;
+        return true;
+    }
 
-    if (strcmp (pointer, "PKGV0002") != 0 && strcmp (pointer, "PKGV0001") != 0)
+//! Check to see if the loader can create archives of this type.
+    bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::E_FILE_ARCHIVE_TYPE fileType) const
     {
-        delete [] pointer;
         return false;
     }
 
-    delete [] pointer;
-    return true;
-}
-
-//! Check to see if the loader can create archives of this type.
-bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::E_FILE_ARCHIVE_TYPE fileType) const
-{
-    return false;
-}
+    CPkgReader::CPkgReader (irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths)
+            : CFileList((file ? file->getFileName() : irr::io::path("")), ignoreCase, ignorePaths), m_file(file)
+    {
+        if (this->m_file)
+        {
+            this->m_file->grab ();
+            this->scanPkgHeader ();
+        }
+    }
 
-CPkgReader::CPkgReader (irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths)
- : CFileList((file ? file->getFileName() : irr::io::path("")), ignoreCase, ignorePaths), mFile(file)
-{
-    if (this->mFile)
+    CPkgReader::~CPkgReader()
     {
-        this->mFile->grab ();
-        this->scanPkgHeader ();
+        if (this->m_file)
+            this->m_file->drop();
     }
-}
 
-CPkgReader::~CPkgReader()
-{
-    if (this->mFile)
-        this->mFile->drop();
-}
+    irr::io::E_FILE_ARCHIVE_TYPE CPkgReader::getType() const
+    {
+        return irr::io::E_FILE_ARCHIVE_TYPE::EFAT_ZIP;
+    }
 
+    const irr::io::IFileList* CPkgReader::getFileList() const
+    {
+        return this;
+    }
 
-//! get the archive type
-irr::io::E_FILE_ARCHIVE_TYPE CPkgReader::getType() const
-{
-	return irr::io::E_FILE_ARCHIVE_TYPE::EFAT_ZIP;
-}
+    void CPkgReader::scanPkgHeader ()
+    {
+        char* headerVersion = this->readSizedString ();
 
-const irr::io::IFileList* CPkgReader::getFileList() const
-{
-	return this;
-}
+        if (strcmp ("PKGV0002", headerVersion) != 0 && strcmp ("PKGV0001", headerVersion) != 0)
+        {
+            delete [] headerVersion;
 
-void CPkgReader::scanPkgHeader ()
-{
-    char* headerVersion = this->readSizedString ();
+            this->m_context->getDevice ()->getLogger ()->log (
+                "unexpected package header", this->m_file->getFileName ().c_str (), irr::ELL_ERROR
+            );
 
-    if (strcmp ("PKGV0002", headerVersion) != 0 && strcmp ("PKGV0001", headerVersion) != 0)
-    {
-        WallpaperEngine::Irrlicht::device->getLogger ()->log ("Unexpected package header... Aborting load", this->mFile->getFileName ().c_str (), irr::ELL_ERROR);
+            return;
+        }
 
         delete [] headerVersion;
-        return;
-    }
-
-    delete [] headerVersion;
+        irr::u32 entriesCount;
 
-    unsigned int entriesCount;
+        this->m_file->read (&entriesCount, 4);
 
-    this->mFile->read (&entriesCount, 4);
 
+        for (irr::u32 i = 0; i < entriesCount; i ++)
+        {
+            char* filename = this->readSizedString ();
+            irr::u32 offset, length;
 
-    for (int i = 0; i < entriesCount; i ++)
-    {
-        char* filename = this->readSizedString ();
-        unsigned int offset, length;
+            this->m_file->read (&offset, 4);
+            this->m_file->read (&length, 4);
 
-        this->mFile->read (&offset, 4);
-        this->mFile->read (&length, 4);
+            this->addItem (filename, offset, length, false);
 
-        this->addItem (filename, offset, length, false);
+            delete [] filename;
+        }
 
-        delete [] filename;
+        // after the header is read we have to update the actual offsets
+        for (irr::u32 i = 0; i < this->m_files.size (); i ++)
+        {
+            this->m_files [i].Offset += this->m_file->getPos ();
+        }
     }
 
-    // after the header is read we have to update the actual offsets
-    for (int i = 0; i < this->Files.size (); i ++)
+    char* CPkgReader::readSizedString ()
     {
-        this->Files [i].Offset += this->mFile->getPos ();
-    }
-}
-
-char* CPkgReader::readSizedString ()
-{
-    unsigned int size;
-    char* pointer;
+        unsigned int size;
+        char* pointer;
 
-    this->mFile->read (&size, 4);
+        this->m_file->read (&size, 4);
 
-    // the string doesnt include the null terminator
-    size ++;
+        // the string doesnt include the null terminator
+        size ++;
 
-    pointer = new char [size];
-    memset (pointer, 0, size);
+        pointer = new char [size];
+        memset (pointer, 0, size);
 
-    this->mFile->read (pointer, size - 1);
+        this->m_file->read (pointer, size - 1);
 
-    return pointer;
-}
-
-irr::io::IReadFile* CPkgReader::createAndOpenFile (const irr::io::path& filename)
-{
-    irr::s32 index = this->findFile (filename, false);
+        return pointer;
+    }
 
-    if (index != -1)
-        return createAndOpenFile (index);
+    irr::io::IReadFile* CPkgReader::createAndOpenFile (const irr::io::path& filename)
+    {
+        irr::s32 index = this->findFile (filename, false);
 
-    return nullptr;
-}
+        if (index != -1)
+            return createAndOpenFile (index);
 
-irr::io::IReadFile* CPkgReader::createAndOpenFile (irr::u32 index)
-{
-    if (index > this->Files.size ())
         return nullptr;
+    }
 
-    const SFileListEntry entry = Files [index];
-    return irr::io::createLimitReadFile (entry.FullName, mFile, entry.Offset, entry.Size);
+    irr::io::IReadFile* CPkgReader::createAndOpenFile (irr::u32 index)
+    {
+        if (index > this->m_files.size ())
+            return nullptr;
+
+        const SFileListEntry entry = m_files [index];
+        return irr::io::createLimitReadFile (entry.FullName, m_file, entry.Offset, entry.Size);
+    }
 }

+ 18 - 19
src/WallpaperEngine/Irrlicht/CPkgReader.h

@@ -2,10 +2,9 @@
 #include <irrlicht/irrlicht.h>
 #include <string>
 
+#include "CContext.h"
 #include "CFileList.h"
 
-using namespace irr;
-
 namespace WallpaperEngine::Irrlicht
 {
 //! Archiveloader capable of loading WAD Archives
@@ -14,36 +13,36 @@ namespace WallpaperEngine::Irrlicht
     public:
 
         //! Constructor
-        CArchiveLoaderPkg(irr::io::IFileSystem *fs);
+        CArchiveLoaderPkg (CContext* context);
 
         //! returns true if the file maybe is able to be loaded by this class
         //! based on the file extension (e.g. ".zip")
-        virtual bool isALoadableFileFormat(const irr::io::path &filename) const;
+        virtual bool isALoadableFileFormat (const irr::io::path &filename) const;
 
         //! Check if the file might be loaded by this class
         /** Check might look into the file.
         \param file File handle to check.
         \return True if file seems to be loadable. */
-        virtual bool isALoadableFileFormat(irr::io::IReadFile *file) const;
+        virtual bool isALoadableFileFormat (irr::io::IReadFile *file) const;
 
         //! Check to see if the loader can create archives of this type.
         /** Check based on the archive type.
         \param fileType The archive type to check.
         \return True if the archile loader supports this type, false if not */
-        virtual bool isALoadableFileFormat(irr::io::E_FILE_ARCHIVE_TYPE fileType) const;
+        virtual bool isALoadableFileFormat (irr::io::E_FILE_ARCHIVE_TYPE fileType) const;
 
         //! Creates an archive from the filename
         /** \param file File handle to check.
         \return Pointer to newly created archive, or 0 upon error. */
         virtual irr::io::IFileArchive *
-        createArchive(const irr::io::path &filename, bool ignoreCase, bool ignorePaths) const;
+        createArchive (const irr::io::path &filename, bool ignoreCase, bool ignorePaths) const;
 
         //! creates/loads an archive from the file.
         //! \return Pointer to the created archive. Returns 0 if loading failed.
-        virtual irr::io::IFileArchive *createArchive(irr::io::IReadFile *file, bool ignoreCase, bool ignorePaths) const;
+        virtual irr::io::IFileArchive *createArchive (irr::io::IReadFile *file, bool ignoreCase, bool ignorePaths) const;
 
     private:
-        irr::io::IFileSystem *FileSystem;
+        CContext* m_context;
     };
 
     class CPkgReader : public virtual irr::io::IFileArchive, virtual CFileList
@@ -51,29 +50,29 @@ namespace WallpaperEngine::Irrlicht
     public:
 
         //! constructor
-        CPkgReader(irr::io::IReadFile *file, bool ignoreCase, bool ignorePaths);
+        CPkgReader (irr::io::IReadFile *file, bool ignoreCase, bool ignorePaths);
 
         //! destructor
-        virtual ~CPkgReader();
+        virtual ~CPkgReader ();
 
         //! opens a file by file name
-        virtual irr::io::IReadFile *createAndOpenFile(const irr::io::path &filename);
+        virtual irr::io::IReadFile *createAndOpenFile (const irr::io::path &filename);
 
         //! opens a file by index
-        virtual irr::io::IReadFile *createAndOpenFile(unsigned int index);
+        virtual irr::io::IReadFile *createAndOpenFile (unsigned int index);
 
         //! returns the list of files
-        virtual const IFileList *getFileList() const;
+        virtual const IFileList *getFileList () const;
 
         //! get the archive type
-        virtual irr::io::E_FILE_ARCHIVE_TYPE getType() const;
+        virtual irr::io::E_FILE_ARCHIVE_TYPE getType () const;
 
     protected:
-        void scanPkgHeader();
+        void scanPkgHeader ();
 
-        char *readSizedString();
+        char *readSizedString ();
 
-        irr::io::IFileSystem *mFileSystem;
-        irr::io::IReadFile *mFile;
+        CContext* m_context;
+        irr::io::IReadFile *m_file;
     };
 }

+ 0 - 8
src/WallpaperEngine/Irrlicht/Irrlicht.cpp

@@ -1,8 +0,0 @@
-#include <WallpaperEngine/Irrlicht/Irrlicht.h>
-
-namespace WallpaperEngine::Irrlicht
-{
-    irr::video::IVideoDriver* driver = nullptr;
-    irr::IrrlichtDevice* device = nullptr;
-    irr::scene::ICameraSceneNode* camera = nullptr;
-}

+ 0 - 10
src/WallpaperEngine/Irrlicht/Irrlicht.h

@@ -1,10 +0,0 @@
-#pragma once
-
-#include <irrlicht/irrlicht.h>
-
-namespace WallpaperEngine::Irrlicht
-{
-    extern irr::video::IVideoDriver* driver;
-    extern irr::IrrlichtDevice* device;
-    extern irr::scene::ICameraSceneNode* camera;
-};

+ 4 - 14
src/WallpaperEngine/Render/Shaders/Compiler.cpp

@@ -6,9 +6,6 @@
 // filesystem
 #include <WallpaperEngine/FileSystem/FileSystem.h>
 
-// video engine
-#include <WallpaperEngine/Irrlicht/Irrlicht.h>
-
 // shader compiler
 #include <WallpaperEngine/Render/Shaders/Compiler.h>
 #include <WallpaperEngine/Core/Core.h>
@@ -242,7 +239,7 @@ namespace WallpaperEngine::Render::Shaders
 
     std::string Compiler::precompile()
     {
-    #define BREAK_IF_ERROR if (this->m_error == true) { WallpaperEngine::Irrlicht::device->getLogger ()->log ("ERROR PRE-COMPILING SHADER", irr::ELL_ERROR); WallpaperEngine::Irrlicht::device->getLogger ()->log (this->m_errorInfo.c_str (), irr::ELL_ERROR); return ""; }
+    #define BREAK_IF_ERROR if (this->m_error == true) { throw std::runtime_error ("ERROR PRE-COMPILING SHADER" + this->m_errorInfo); }
         // parse the shader and find #includes and such things and translate them to the correct name
         // also remove any #version definition to prevent errors
         std::string::const_iterator it = this->m_content.begin ();
@@ -441,12 +438,6 @@ namespace WallpaperEngine::Render::Shaders
             }
         }
 
-        if (this->m_recursive == false)
-        {
-            WallpaperEngine::Irrlicht::device->getLogger ()->log ("Compiled shader output for", this->m_file.c_str ());
-            WallpaperEngine::Irrlicht::device->getLogger ()->log (this->m_compiledContent.c_str ());
-        }
-
         return this->m_compiledContent;
     #undef BREAK_IF_ERROR
     }
@@ -462,8 +453,7 @@ namespace WallpaperEngine::Render::Shaders
 
         if (combo == data.end () || defvalue == data.end ())
         {
-            WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse combo information", irr::ELL_ERROR);
-            return;
+            throw std::runtime_error ("cannot parse combo information");
         }
 
         // check the combos
@@ -488,7 +478,7 @@ namespace WallpaperEngine::Render::Shaders
             }
             else
             {
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse combo information, unknown type", irr::ELL_ERROR);
+                throw std::runtime_error ("cannot parse combo information, unknown type");
             }
         }
     }
@@ -504,7 +494,7 @@ namespace WallpaperEngine::Render::Shaders
         if (material == data.end () || defvalue == data.end ())
         {
             if (type != "sampler2D")
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot parse parameter info for ", name.c_str (), irr::ELL_ERROR);
+                throw std::runtime_error ("cannot parse parameter info for " + name);
 
             return;
         }

+ 4 - 3
src/WallpaperEngine/effect.cpp

@@ -1,11 +1,12 @@
 #include <WallpaperEngine/FileSystem/FileSystem.h>
 
+#include "WallpaperEngine/Irrlicht/CContext.h"
 #include "WallpaperEngine/Render/Shaders/Compiler.h"
 #include "effect.h"
-#include "WallpaperEngine/Irrlicht/Irrlicht.h"
 #include "WallpaperEngine/Core/Core.h"
 
 extern irr::f32 g_Time;
+extern WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
 
 namespace WallpaperEngine
 {
@@ -97,7 +98,7 @@ namespace WallpaperEngine
             this->m_fragShader = new WallpaperEngine::Render::Shaders::Compiler (fragpath, WallpaperEngine::Render::Shaders::Compiler::Type::Type_Pixel, &this->m_combos, false);
             this->m_vertShader = new WallpaperEngine::Render::Shaders::Compiler (vertpath, WallpaperEngine::Render::Shaders::Compiler::Type::Type_Vertex, &this->m_combos, false);
 
-            this->m_materialType = WallpaperEngine::Irrlicht::driver->getGPUProgrammingServices ()
+            this->m_materialType = IrrlichtContext->getDevice ()->getVideoDriver ()->getGPUProgrammingServices ()
                 ->addHighLevelShaderMaterial (
                     this->m_vertShader->precompile ().c_str (), "main", irr::video::EVST_VS_2_0,
                     this->m_fragShader->precompile ().c_str (), "main", irr::video::EPST_PS_2_0,
@@ -336,7 +337,7 @@ namespace WallpaperEngine
             }
             else
             {
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Unknown type for combo value", name.c_str (), irr::ELL_ERROR);
+                IrrlichtContext->getDevice ()->getLogger ()->log ("Unknown type for combo value", name.c_str (), irr::ELL_ERROR);
             }
         }
     }

+ 5 - 3
src/WallpaperEngine/image.cpp

@@ -5,9 +5,11 @@
 #include <WallpaperEngine/object3d.h>
 #include <WallpaperEngine/image.h>
 
-#include <WallpaperEngine/Irrlicht/Irrlicht.h>
+#include <WallpaperEngine/Irrlicht/CContext.h>
 #include <WallpaperEngine/Core/Core.h>
 
+extern WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
+
 namespace WallpaperEngine
 {
     image::image (json json_data, WallpaperEngine::object* parent) : object3d (object3d::Type::Type_Material, parent)
@@ -153,8 +155,8 @@ namespace WallpaperEngine
                 0, 1, 2, 3
         };
 
-        WallpaperEngine::Irrlicht::driver->setMaterial (this->getMaterial ());
-        WallpaperEngine::Irrlicht::driver->drawVertexPrimitiveList (this->m_vertices, 4, indices, 1, irr::video::EVT_STANDARD, irr::scene::EPT_QUADS, irr::video::EIT_16BIT);
+        IrrlichtContext->getDevice ()->getVideoDriver ()->setMaterial (this->getMaterial ());
+        IrrlichtContext->getDevice ()->getVideoDriver ()->drawVertexPrimitiveList (this->m_vertices, 4, indices, 1, irr::video::EVT_STANDARD, irr::scene::EPT_QUADS, irr::video::EIT_16BIT);
     }
 
 }

+ 0 - 1
src/WallpaperEngine/project.cpp

@@ -6,7 +6,6 @@
 #include "WallpaperEngine/FileSystem/FileSystem.h"
 
 #include "project.h"
-#include "WallpaperEngine/Irrlicht/Irrlicht.h"
 
 namespace WallpaperEngine
 {

+ 6 - 8
src/WallpaperEngine/sound.cpp

@@ -1,11 +1,9 @@
-//
-// Created by almamu on 17/05/19.
-//
-
 #include <SDL_rwops.h>
 #include <SDL_mixer.h>
 #include "sound.h"
-#include "WallpaperEngine/Irrlicht/Irrlicht.h"
+#include "WallpaperEngine/Irrlicht/CContext.h"
+
+extern WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
 
 namespace WallpaperEngine
 {
@@ -31,7 +29,7 @@ namespace WallpaperEngine
         {
             SDL_RWops* sdlRwops = nullptr;
             Mix_Music* music = nullptr;
-            irr::io::IReadFile* readfile = WallpaperEngine::Irrlicht::device->getFileSystem ()->createAndOpenFile ((*cur).c_str ());
+            irr::io::IReadFile* readfile = IrrlichtContext->getDevice ()->getFileSystem ()->createAndOpenFile ((*cur).c_str ());
             int filesize = readfile->getSize ();
             char* filebuffer = new char [filesize];
 
@@ -43,7 +41,7 @@ namespace WallpaperEngine
 
             if (music == nullptr)
             {
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot load audio", Mix_GetError (), irr::ELL_ERROR);
+                IrrlichtContext->getDevice ()->getLogger ()->log ("Cannot load audio", Mix_GetError (), irr::ELL_ERROR);
             }
 
             this->m_bufferReader.push_back (sdlRwops);
@@ -58,7 +56,7 @@ namespace WallpaperEngine
         {
             if (Mix_PlayMusic ((*mixcur), -1) == -1)
             {
-                WallpaperEngine::Irrlicht::device->getLogger ()->log ("Cannot play audio", Mix_GetError (), irr::ELL_ERROR);
+                IrrlichtContext->getDevice ()->getLogger ()->log ("Cannot play audio", Mix_GetError (), irr::ELL_ERROR);
             }
         }
     }

+ 4 - 2
src/WallpaperEngine/texture.cpp

@@ -2,13 +2,15 @@
 #include <stdexcept>
 #include <lz4.h>
 
-#include "WallpaperEngine/Irrlicht/Irrlicht.h"
+#include <WallpaperEngine/Irrlicht/CContext.h>
+
+extern WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
 
 namespace WallpaperEngine
 {
     texture::texture (irr::io::path& file)
     {
-        this->m_texture = WallpaperEngine::Irrlicht::driver->getTexture (file);
+        this->m_texture = IrrlichtContext->getDevice ()->getVideoDriver ()->getTexture (file);
     }
 
     irr::video::ITexture* texture::getIrrTexture ()

+ 7 - 3
src/WallpaperEngine/video/material.cpp

@@ -1,5 +1,7 @@
-#include <WallpaperEngine/Irrlicht/Irrlicht.h>
 #include <WallpaperEngine/video/material.h>
+#include <WallpaperEngine/Irrlicht/CContext.h>
+
+extern WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
 
 namespace WallpaperEngine
 {
@@ -56,8 +58,10 @@ namespace WallpaperEngine
                     0, 1, 2, 3
             };
 
-            WallpaperEngine::Irrlicht::driver->setMaterial (m_material);
-            WallpaperEngine::Irrlicht::driver->drawVertexPrimitiveList (m_vertices, 4, indices, 1, irr::video::EVT_STANDARD, irr::scene::EPT_QUADS, irr::video::EIT_16BIT);
+            IrrlichtContext->getDevice ()->getVideoDriver ()->setMaterial (m_material);
+            IrrlichtContext->getDevice ()->getVideoDriver ()->drawVertexPrimitiveList (
+                m_vertices, 4, indices, 1, irr::video::EVT_STANDARD, irr::scene::EPT_QUADS, irr::video::EIT_16BIT
+            );
         }
     }
 }

+ 12 - 9
src/WallpaperEngine/video/renderer.cpp

@@ -1,5 +1,7 @@
-#include <WallpaperEngine/Irrlicht/Irrlicht.h>
 #include <WallpaperEngine/video/renderer.h>
+#include <WallpaperEngine/Irrlicht/CContext.h>
+
+extern WallpaperEngine::Irrlicht::CContext* IrrlichtContext;
 
 namespace WallpaperEngine
 {
@@ -31,19 +33,19 @@ namespace WallpaperEngine
                     znear,
                     zfar
             );
-            WallpaperEngine::Irrlicht::camera = WallpaperEngine::Irrlicht::device->getSceneManager ()->addCameraSceneNode (0, position, lookat);
-            WallpaperEngine::Irrlicht::camera->setProjectionMatrix (orthoProjection);
+            s_camera = IrrlichtContext->getDevice ()->getSceneManager ()->addCameraSceneNode (0, position, lookat);
+            s_camera->setProjectionMatrix (orthoProjection);
 
-            WallpaperEngine::Irrlicht::driver->setTransform (irr::video::ETS_PROJECTION, orthoProjection);
-            WallpaperEngine::Irrlicht::driver->setTransform (irr::video::ETS_VIEW, identity);
-            WallpaperEngine::Irrlicht::driver->setTransform (irr::video::ETS_WORLD, identity);
+            IrrlichtContext->getDevice ()->getVideoDriver ()->setTransform (irr::video::ETS_PROJECTION, orthoProjection);
+            IrrlichtContext->getDevice ()->getVideoDriver ()->setTransform (irr::video::ETS_VIEW, identity);
+            IrrlichtContext->getDevice ()->getVideoDriver ()->setTransform (irr::video::ETS_WORLD, identity);
         }
 
         void renderer::render ()
         {
-            if (WallpaperEngine::Irrlicht::driver == nullptr) return;
+            if (IrrlichtContext->getDevice ()->getVideoDriver () == nullptr) return;
 
-            WallpaperEngine::Irrlicht::driver->beginScene(true, true, irr::video::SColor(0, 0, 0, 0));
+            IrrlichtContext->getDevice ()->getVideoDriver ()->beginScene(true, true, irr::video::SColor(0, 0, 0, 0));
 
             std::vector<node*>::const_iterator cur = s_nodes.begin ();
             std::vector<node*>::const_iterator end = s_nodes.end ();
@@ -53,9 +55,10 @@ namespace WallpaperEngine
                 (*cur)->render ();
             }
 
-            WallpaperEngine::Irrlicht::driver->endScene ();
+            IrrlichtContext->getDevice ()->getVideoDriver ()->endScene ();
         }
 
         std::vector<node*> renderer::s_nodes;
+        irr::scene::ICameraSceneNode* renderer::s_camera;
     }
 };

+ 1 - 0
src/WallpaperEngine/video/renderer.h

@@ -20,6 +20,7 @@ namespace WallpaperEngine
 
         private:
             static std::vector<node*> s_nodes;
+            static irr::scene::ICameraSceneNode* s_camera;
         };
     }
 }