Compare commits

..

2 Commits

Author SHA1 Message Date
Alexis Maiquez
061b3bd2e8
Merge 2d6675db0b into be0fc25e72 2025-09-11 15:10:29 +00:00
Almamu
2d6675db0b refactor: overhaul the filesystem layer 2025-09-11 17:10:23 +02:00
58 changed files with 859 additions and 905 deletions

View File

@ -267,23 +267,21 @@ add_executable(
src/WallpaperEngine/Application/CWallpaperApplication.cpp
src/WallpaperEngine/Application/CWallpaperApplication.h
src/WallpaperEngine/Assets/CPackageLoadException.cpp
src/WallpaperEngine/Assets/CPackageLoadException.h
src/WallpaperEngine/Assets/CAssetLoadException.cpp
src/WallpaperEngine/Assets/CAssetLoadException.h
src/WallpaperEngine/Assets/CContainer.h
src/WallpaperEngine/Assets/CContainer.cpp
src/WallpaperEngine/Assets/CVirtualContainer.h
src/WallpaperEngine/Assets/CVirtualContainer.cpp
src/WallpaperEngine/Assets/CCombinedContainer.h
src/WallpaperEngine/Assets/CCombinedContainer.cpp
src/WallpaperEngine/Assets/CDirectory.h
src/WallpaperEngine/Assets/CDirectory.cpp
src/WallpaperEngine/Assets/CPackage.h
src/WallpaperEngine/Assets/CPackage.cpp
src/WallpaperEngine/Assets/ITexture.h
src/WallpaperEngine/Assets/CTexture.h
src/WallpaperEngine/Assets/CTexture.cpp
src/WallpaperEngine/Assets/CAssetLoadException.cpp
src/WallpaperEngine/Assets/CAssetLoadException.h
src/WallpaperEngine/FileSystem/Container.h
src/WallpaperEngine/FileSystem/Container.cpp
src/WallpaperEngine/FileSystem/Adapters/Types.h
src/WallpaperEngine/FileSystem/Adapters/Directory.cpp
src/WallpaperEngine/FileSystem/Adapters/Directory.h
src/WallpaperEngine/FileSystem/Adapters/Package.cpp
src/WallpaperEngine/FileSystem/Adapters/Package.h
src/WallpaperEngine/FileSystem/Adapters/Virtual.cpp
src/WallpaperEngine/FileSystem/Adapters/Virtual.h
src/WallpaperEngine/Audio/Drivers/Recorders/CPulseAudioPlaybackRecorder.cpp
src/WallpaperEngine/Audio/Drivers/Recorders/CPulseAudioPlaybackRecorder.h
@ -404,6 +402,7 @@ add_executable(
src/WallpaperEngine/Data/Assets/Types.h
src/WallpaperEngine/Data/Assets/Texture.h
src/WallpaperEngine/Data/Assets/Package.h
src/WallpaperEngine/Data/Model/Types.h
src/WallpaperEngine/Data/Model/Project.h
src/WallpaperEngine/Data/Model/Wallpaper.h
@ -437,6 +436,8 @@ add_executable(
src/WallpaperEngine/Data/Parsers/ModelParser.h
src/WallpaperEngine/Data/Parsers/ShaderConstantParser.cpp
src/WallpaperEngine/Data/Parsers/ShaderConstantParser.h
src/WallpaperEngine/Data/Parsers/PackageParser.cpp
src/WallpaperEngine/Data/Parsers/PackageParser.h
src/WallpaperEngine/Data/Parsers/PropertyParser.cpp
src/WallpaperEngine/Data/Parsers/PropertyParser.h
src/WallpaperEngine/Data/Parsers/TextureParser.cpp
@ -450,7 +451,11 @@ add_executable(
${WAYLAND_SOURCES}
${X11_SOURCES}
${DEMOMODE_SOURCES})
${DEMOMODE_SOURCES}
src/WallpaperEngine/FileSystem/Adapters/Package.h
src/WallpaperEngine/FileSystem/Adapters/Package.cpp
src/WallpaperEngine/FileSystem/Adapters/Virtual.h
src/WallpaperEngine/FileSystem/Adapters/Virtual.cpp)
target_link_libraries (linux-wallpaperengine PUBLIC
${OPENGL_LIBRARIES}

View File

@ -3,9 +3,8 @@
#include "Steam/FileSystem/FileSystem.h"
#include "WallpaperEngine/Application/CApplicationState.h"
#include "WallpaperEngine/Assets/CAssetLoadException.h"
#include "WallpaperEngine/Assets/CDirectory.h"
#include "WallpaperEngine/Assets/CVirtualContainer.h"
#include "WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h"
#include "WallpaperEngine/FileSystem/Container.h"
#include "WallpaperEngine/Logging/CLog.h"
#include "WallpaperEngine/Render/CRenderContext.h"
#include "WallpaperEngine/Render/Drivers/CVideoFactories.h"
@ -32,6 +31,7 @@ float g_Daytime;
using namespace WallpaperEngine::Application;
using namespace WallpaperEngine::Data::Model;
using namespace WallpaperEngine::FileSystem;
CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
m_context (context) {
@ -41,21 +41,30 @@ CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
}
ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg) const {
auto container = std::make_unique <CCombinedContainer> ();
const std::filesystem::path basepath = bg;
auto container = std::make_unique <Container> ();
container->add (std::make_unique<CDirectory> (basepath));
container->addPkg (basepath / "scene.pkg");
container->addPkg (basepath / "gifscene.pkg");
std::filesystem::path path (bg);
container->mount (path, "/");
try {
container->mount (path / "scene.pkg", "/");
} catch (std::runtime_error&) {
}
try {
container->add (std::make_unique <CDirectory> (this->m_context.settings.general.assets));
} catch (CAssetLoadException&) {
container->mount (path / "gifscene.pkg", "/");
} catch (std::runtime_error&) {
}
try {
container->mount (this->m_context.settings.general.assets, "/");
} catch (std::runtime_error&) {
sLog.exception ("Cannot find a valid assets folder, resolved to ", this->m_context.settings.general.assets);
}
// TODO: move this somewhere else?
auto virtualContainer = std::make_unique <CVirtualContainer> ();
auto& vfs = container->getVFS ();
//
// Had to get a little creative with the effects to achieve the same bloom effect without any custom code
@ -66,21 +75,21 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
// add the effect file for screen bloom
// add some model for the image element even if it's going to waste rendering cycles
virtualContainer->add (
vfs.add (
"effects/wpenginelinux/bloomeffect.json",
{
{"name", "camerabloom_wpengine_linux"},
{"group", "wpengine_linux_camera"},
{"dependencies", json::array ()},
{"dependencies", JSON::array ()},
{"passes",
json::array (
JSON::array (
{
{
{"material", "materials/util/downsample_quarter_bloom.json"},
{"target", "_rt_4FrameBuffer"},
{
"bind",
json::array (
JSON::array (
{
{
{"name", "_rt_FullFrameBuffer"},
@ -95,7 +104,7 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
{"target", "_rt_8FrameBuffer"},
{
"bind",
json::array (
JSON::array (
{
{
{"name", "_rt_4FrameBuffer"},
@ -110,7 +119,7 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
{"target", "_rt_Bloom"},
{
"bind",
json::array (
JSON::array (
{
{
{"name", "_rt_8FrameBuffer"},
@ -125,7 +134,7 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
{"target", "_rt_FullFrameBuffer"},
{
"bind",
json::array (
JSON::array (
{
{
{"name", "_rt_imageLayerComposite_-1_a"},
@ -145,17 +154,17 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
}
);
virtualContainer->add (
vfs.add (
"models/wpenginelinux.json",
{
{"material","materials/wpenginelinux.json"}
}
);
virtualContainer->add(
vfs.add(
"materials/wpenginelinux.json",
{
{"passes", json::array (
{"passes", JSON::array (
{
{
{"blending", "normal"},
@ -163,13 +172,13 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
{"depthtest", "disabled"},
{"depthwrite", "disabled"},
{"shader", "genericimage2"},
{"textures", json::array ({"_rt_FullFrameBuffer"})}
{"textures", JSON::array ({"_rt_FullFrameBuffer"})}
}
}
)}}
);
virtualContainer->add(
vfs.add(
"shaders/commands/copy.frag",
"uniform sampler2D g_Texture0;\n"
"in vec2 v_TexCoord;\n"
@ -177,7 +186,7 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
"out_FragColor = texture (g_Texture0, v_TexCoord);\n"
"}"
);
virtualContainer->add(
vfs.add(
"shaders/commands/copy.vert",
"in vec3 a_Position;\n"
"in vec2 a_TexCoord;\n"
@ -188,8 +197,6 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
"}"
);
container->add (std::move(virtualContainer));
return container;
}
@ -212,7 +219,7 @@ void CWallpaperApplication::loadBackgrounds () {
ProjectUniquePtr CWallpaperApplication::loadBackground (const std::string& bg) {
auto container = this->setupContainer (bg);
auto json = WallpaperEngine::Data::JSON::JSON::parse (container->readFileAsString ("project.json"));
auto json = WallpaperEngine::Data::JSON::JSON::parse (container->readString ("project.json"));
return WallpaperEngine::Data::Parsers::ProjectParser::parse (json, std::move(container));
}

View File

@ -2,8 +2,6 @@
#include "WallpaperEngine/Application/CApplicationContext.h"
#include "WallpaperEngine/Assets/CCombinedContainer.h"
#include "WallpaperEngine/Render/CRenderContext.h"
#include "WallpaperEngine/Render/CWallpaper.h"
#include "WallpaperEngine/Render/Drivers/CGLFWOpenGLDriver.h"

View File

@ -3,6 +3,7 @@
#include <exception>
#include <string>
// TODO: REWRITE THIS ONE TO MAKE MORE SENSE, IT REALLY MEANS "FILE-RELATED EXCEPTION"
namespace WallpaperEngine::Assets {
class CAssetLoadException final : public std::exception {
public:

View File

@ -1,57 +0,0 @@
#include "CCombinedContainer.h"
#include "CAssetLoadException.h"
#include "CPackage.h"
#include "CPackageLoadException.h"
#include "WallpaperEngine/Logging/CLog.h"
using namespace WallpaperEngine::Assets;
CCombinedContainer::CCombinedContainer () : CContainer () {}
void CCombinedContainer::add (std::unique_ptr<CContainer> container) {
this->m_containers.emplace_back (std::move(container));
}
void CCombinedContainer::addPkg (const std::filesystem::path& path) {
try {
// add the package to the list
this->add (std::make_unique<CPackage> (path));
sLog.out ("Detected ", path.filename (), " file at ", path, ". Adding to list of searchable paths");
} catch (CPackageLoadException&) {
// ignore this error, the package file was not found
sLog.out ("No ", path.filename (), " file found at ", path, ". Defaulting to normal folder storage");
} catch (std::runtime_error& ex) {
// the package was found but there was an error loading it (wrong header or something)
sLog.exception ("Failed to load ", path.filename(), " file: ", ex.what ());
}
}
std::filesystem::path CCombinedContainer::resolveRealFile (const std::filesystem::path& filename) const {
for (const auto& cur : this->m_containers) {
try {
// try to read the file on the current container, if the file doesn't exists
// an exception will be thrown
return cur->resolveRealFile (filename);
} catch (CAssetLoadException&) {
// not found in this container, next try
}
}
// no container was able to load the file, abort!
throw CAssetLoadException (filename, "Cannot resolve file in any of the containers");
}
std::shared_ptr<const uint8_t[]> CCombinedContainer::readFile (const std::filesystem::path& filename, uint32_t* length) const {
for (const auto& cur : this->m_containers) {
try {
// try to read the file on the current container, if the file doesn't exists
// an exception will be thrown
return cur->readFile (filename, length);
} catch (CAssetLoadException& e) {
// not found in this container, next try
}
}
// no container was able to load the file, abort!
throw CAssetLoadException (filename, "Cannot find file in any of the containers");
}

View File

@ -1,37 +0,0 @@
#pragma once
#include "CContainer.h"
#include <filesystem>
#include <stdexcept>
#include <vector>
namespace WallpaperEngine::Assets {
/**
* A meta-container that allows backgrounds to have files spread across different containers
*/
class CCombinedContainer final : public CContainer {
public:
CCombinedContainer ();
/**
* Adds a container to the list
*
* @param container
*/
void add (std::unique_ptr<CContainer> container);
/**
* Adds the given package to the list
*
* @param path
*/
void addPkg (const std::filesystem::path& path);
[[nodiscard]] std::filesystem::path resolveRealFile (const std::filesystem::path& filename) const override;
[[nodiscard]] std::shared_ptr<const uint8_t[]> readFile (const std::filesystem::path& filename, uint32_t* length) const override;
private:
/** The list of containers to search files off from */
std::vector<std::unique_ptr<CContainer>> m_containers {};
};
}; // namespace WallpaperEngine::Assets

View File

@ -1,88 +0,0 @@
#include "CContainer.h"
#include "CAssetLoadException.h"
#include "CTexture.h"
#include "WallpaperEngine/Data/Utils/BinaryReader.h"
#include "WallpaperEngine/Data/Utils/MemoryStream.h"
#include "WallpaperEngine/Data/Parsers/TextureParser.h"
#include "WallpaperEngine/Logging/CLog.h"
#include <cstring>
#include <filesystem>
#include <utility>
using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Data::Utils;
using namespace WallpaperEngine::Data::Parsers;
std::filesystem::path CContainer::resolveRealFile (const std::filesystem::path& filename) const {
throw CAssetLoadException (filename, "Cannot resolve physical file in this container");
}
std::shared_ptr <const ITexture> CContainer::readTexture (const std::filesystem::path& filename) const {
// get the texture's filename (usually .tex)
std::filesystem::path texture = "materials" / std::filesystem::path (filename.string ().append (".tex"));
uint32_t length = 0;
const auto textureContents = this->readFile (texture, &length);
// TODO: MAKE PROPER USE OF I/OSTREAMS IN THE CLASS INSTEAD OF INSTANTIATING THINGS HERE...
auto buffer = MemoryStream (reinterpret_cast<char*> (const_cast<unsigned char*> (&textureContents.get () [0])), length);
auto istream = std::istream (&buffer);
auto binaryReader = BinaryReader (istream);
const auto result = std::make_shared<CTexture> (TextureParser::parse (binaryReader));
#if !NDEBUG
glObjectLabel (GL_TEXTURE, result->getTextureID (0), -1, texture.c_str ());
#endif /* NDEBUG */
return result;
}
std::string CContainer::readShader (const std::filesystem::path& filename) const {
std::filesystem::path shader = filename;
auto it = shader.begin ();
// detect workshop shaders and check if there's a
if (*it++ == "workshop") {
const std::filesystem::path workshopId = *it++;
if (++it != shader.end ()) {
const std::filesystem::path& shaderfile = *it;
try {
shader = std::filesystem::path ("zcompat") / "scene" / "shaders" / workshopId / shaderfile;
// replace the old path with the new one
std::string contents = this->readFileAsString (shader);
sLog.out ("Replaced ", filename, " with compat ", shader);
return contents;
} catch (CAssetLoadException&) {}
}
}
return this->readFileAsString ("shaders" / filename);
}
std::string CContainer::readVertexShader (const std::filesystem::path& filename) const {
std::filesystem::path shader = filename;
shader.replace_extension (".vert");
return this->readShader (shader);
}
std::string CContainer::readFragmentShader (const std::filesystem::path& filename) const {
std::filesystem::path shader = filename;
shader.replace_extension (".frag");
return this->readShader (shader);
}
std::string CContainer::readIncludeShader (const std::filesystem::path& filename) const {
return this->readFileAsString ("shaders" / filename);
}
std::string CContainer::readFileAsString (const std::filesystem::path& filename) const {
uint32_t length = 0;
return {
reinterpret_cast<const char*> (this->readFile (filename, &length).get ()), length
};
}

View File

@ -1,93 +0,0 @@
#pragma once
#include "WallpaperEngine/Assets/ITexture.h"
#include <filesystem>
#include <string>
namespace WallpaperEngine::Assets {
class ITexture;
/**
* File container, provides access to files for backgrounds
*/
class CContainer {
public:
virtual ~CContainer () = default;
/**
* Resolves the full path to the specified file in the filesystem
*
* @param filename
* @return
*/
[[nodiscard]] virtual std::filesystem::path resolveRealFile (const std::filesystem::path& filename) const;
/**
* Reads the given file from the container and returns it's data
* Additionally sets a length parameter to return back the file's length
*
* The returned string must be deleted[] by the caller
*
* @param filename The file to read
* @param length The file's length after it's been read, null for not getting anything back
*
* @return
*/
[[nodiscard]] virtual std::shared_ptr<const uint8_t[]> readFile (const std::filesystem::path& filename, uint32_t* length) const = 0;
/**
* Wrapper for readFile, appends the texture extension at the end of the filename
*
* @param filename The texture name (without the .tex)
*
* @return
*/
[[nodiscard]] std::shared_ptr <const ITexture> readTexture (const std::filesystem::path& filename) const;
/**
* Wrapper for readFile, checks for compat versions of the given shader file
*
* @param filename
*
* @return The shader code as an string to be used
*/
[[nodiscard]] std::string readShader (const std::filesystem::path& filename) const;
/**
* Wrapper for readFile, appends the .vert extension at the end and opens the given shader file
*
* @param filename
*
* @return The shader code as an string to be used
*/
[[nodiscard]] std::string readVertexShader (const std::filesystem::path& filename) const;
/**
* Wrapper for readFile, appends the .frag extension at the end and opens the given shader file
*
* @param filename
*
* @return The shader code as an string to be used
*/
[[nodiscard]] std::string readFragmentShader (const std::filesystem::path& filename) const;
/**
* Wrapper for readFile, appends the .h extension at the end and opens the given shader file
*
* @param filename
*
* @return The shader code as an string to be used
*/
[[nodiscard]] std::string readIncludeShader (const std::filesystem::path& filename) const;
/**
* Reads a file as string
*
* @param filename
*
* @return The file's contents as string
*/
[[nodiscard]] std::string readFileAsString (const std::filesystem::path& filename) const;
};
} // namespace WallpaperEngine::Assets

View File

@ -1,85 +0,0 @@
#include "CAssetLoadException.h"
#include "CDirectory.h"
using namespace WallpaperEngine::Assets;
CDirectory::CDirectory (const std::filesystem::path& basepath) {
try {
// resolve the path to it's real location
std::filesystem::path finalpath = std::filesystem::canonical(basepath);
std::filesystem::file_status status = std::filesystem::status (finalpath);
if (!std::filesystem::exists (finalpath)) {
throw CAssetLoadException (basepath, "Cannot find directory");
}
if (!std::filesystem::is_directory(status)) {
throw CAssetLoadException (basepath, "Expected directory but found a file");
}
this->m_basepath = finalpath;
} catch (std::bad_alloc&) {
throw CAssetLoadException (basepath, "Cannot allocate memory");
} catch (std::filesystem::filesystem_error& e) {
throw CAssetLoadException (basepath, e.what ());
}
}
std::filesystem::path CDirectory::resolveRealFile (const std::filesystem::path& filename) const {
try {
std::filesystem::path final = std::filesystem::canonical (this->m_basepath / filename);
// first validate the path, so the message doesn't reflect if the file exists or not unless it's under the actual directory
if (final.string ().find (this->m_basepath.string ()) != 0) {
throw CAssetLoadException (filename, "File is not a child of the given directory");
}
std::filesystem::file_status status = std::filesystem::status (final);
if (!std::filesystem::exists (final)) {
throw CAssetLoadException (filename, "Cannot find file");
}
if (!std::filesystem::is_regular_file (status)) {
throw CAssetLoadException (filename, "Expected file but found a directory");
}
return final;
} catch (std::filesystem::filesystem_error& e) {
throw CAssetLoadException (filename, e.what ());
}
}
std::shared_ptr<const uint8_t[]> CDirectory::readFile (const std::filesystem::path& filename, uint32_t* length) const {
std::filesystem::path final = this->resolveRealFile (filename);
FILE* fp = fopen (final.c_str (), "rb");
if (fp == nullptr) {
throw CAssetLoadException (filename, "Cannot open file for reading");
}
try {
// go to the end, get the position and return to the beginning
fseek (fp, 0, SEEK_END);
const long size = ftell (fp);
fseek (fp, 0, SEEK_SET);
// now read the whole file
std::shared_ptr<uint8_t[]> contents = std::shared_ptr<uint8_t[]>(new uint8_t [size]);
if (fread (contents.get(), size, 1, fp) != 1) {
throw CAssetLoadException (filename, "Unexpected error when reading the file");
}
if (length != nullptr) {
*length = size;
}
fclose (fp);
return contents;
} catch (std::filesystem::filesystem_error& e) {
fclose (fp);
throw CAssetLoadException (filename, e.what ());
}
}

View File

@ -1,26 +0,0 @@
#pragma once
#include <filesystem>
#include <map>
#include <stdexcept>
#include <string>
#include "CContainer.h"
#include "CFileEntry.h"
namespace WallpaperEngine::Assets {
/**
* Directory container implementation, provides access to background files under a specific directory
*/
class CDirectory final : public CContainer {
public:
explicit CDirectory (const std::filesystem::path& basepath);
[[nodiscard]] std::filesystem::path resolveRealFile (const std::filesystem::path& filename) const override;
[[nodiscard]] std::shared_ptr<const uint8_t[]> readFile (const std::filesystem::path& filename, uint32_t* length) const override;
private:
/** The basepath for the directory */
std::filesystem::path m_basepath {};
};
} // namespace WallpaperEngine::Assets

View File

@ -1,22 +0,0 @@
#pragma once
#include <cstdint>
#include <utility>
namespace WallpaperEngine::Assets {
/**
* File cache entry to prevent hit the disk when loading the same file multiple times
*/
class CFileEntry {
public:
CFileEntry (std::shared_ptr<const uint8_t[]> content, uint32_t length) :
content (std::move(content)),
length (length) {}
~CFileEntry() = default;
/** File contents */
std::shared_ptr<const uint8_t[]> content = nullptr;
/** File length */
uint32_t length = 0;
};
} // namespace WallpaperEngine::Assets

View File

@ -1,135 +0,0 @@
#include "CPackage.h"
#include "CAssetLoadException.h"
#include "CPackageLoadException.h"
#include "WallpaperEngine/Logging/CLog.h"
#include <sstream>
#include <utility>
using namespace WallpaperEngine::Assets;
class CPackageEntry {
public:
CPackageEntry (std::string filename, uint32_t offset, uint32_t length) :
filename (filename),
offset (offset),
length (length) {}
std::string filename;
uint32_t offset;
uint32_t length;
};
CPackage::CPackage (std::filesystem::path path) : m_path (std::move (path)) {
this->init ();
}
std::shared_ptr<const uint8_t[]> CPackage::readFile (const std::filesystem::path& filename, uint32_t* length) const {
const auto it = this->m_contents.find (filename);
if (it == this->m_contents.end ())
throw CAssetLoadException (filename, "Cannot find the file in the package");
// set file length if required
if (length != nullptr)
*length = it->second->length;
return it->second->content;
}
void CPackage::init () {
FILE* fp = fopen (this->m_path.c_str (), "rb+");
if (fp == nullptr)
throw CPackageLoadException (this->m_path, std::to_string (errno));
// first validate header
this->validateHeader (fp);
// header is okay, load everything into memory
this->loadFiles (fp);
fclose (fp);
}
char* CPackage::readSizedString (FILE* fp) {
unsigned int length = 0;
if (fread (&length, sizeof (unsigned int), 1, fp) != 1)
sLog.exception ("Cannot read sized string length on file ", this->m_path);
// account for 0 termination of the string
length++;
char* pointer = new char [length];
memset (pointer, 0, length);
// read only the string bytes so the last one in the memory is 0
length--;
// read data from file
if (fread (pointer, sizeof (char), length, fp) != length)
sLog.exception ("Not enough bytes to read string of length ", length, " on file ", this->m_path);
return pointer;
}
uint32_t CPackage::readInteger (FILE* fp) {
uint32_t output;
if (fread (&output, sizeof (uint32_t), 1, fp) != 1)
sLog.exception ("Not enough bytes to read an integer from file ", this->m_path);
return output;
}
void CPackage::validateHeader (FILE* fp) {
const char* pointer = this->readSizedString (fp);
if (strncmp ("PKGV", pointer, 4) != 0) {
std::stringstream msg;
msg << "Expected PKGV indicator, found " << pointer;
delete [] pointer;
throw std::runtime_error (msg.str ());
}
// free memory
delete [] pointer;
}
void CPackage::loadFiles (FILE* fp) {
const uint32_t count = this->readInteger (fp);
std::vector<CPackageEntry> list;
for (uint32_t index = 0; index < count; index++) {
// first read the filename
char* filename = this->readSizedString (fp);
uint32_t offset = this->readInteger (fp);
uint32_t length = this->readInteger (fp);
// add the file to the list
list.emplace_back (filename, offset, length);
// only free filename, the file's contents are stored in a map for a later use
delete [] filename;
}
// get current baseOffset, this is where the files start
const long baseOffset = ftell (fp);
for (const auto& cur : list) {
const long offset = cur.offset + baseOffset;
// with all the data we can jump to the offset and read the content
if (fseek (fp, offset, SEEK_SET) != 0)
sLog.exception ("Cannot find file ", cur.filename, " from package ", this->m_path);
// allocate memory for the file's contents and read it from the file
std::shared_ptr<uint8_t[]> contents = std::shared_ptr<uint8_t[]>(new uint8_t [cur.length]);
if (fread (contents.get(), cur.length, 1, fp) != 1) {
sLog.exception ("Cannot read file ", cur.filename, " contents from package ", this->m_path);
}
// add the file to the map
this->m_contents.insert_or_assign (cur.filename, std::make_unique<CFileEntry> (contents, cur.length));
}
}

View File

@ -1,68 +0,0 @@
#pragma once
#include <cstring>
#include <exception>
#include <filesystem>
#include <map>
#include <stdexcept>
#include <string>
#include <vector>
#include "CContainer.h"
#include "CFileEntry.h"
namespace WallpaperEngine::Assets {
/**
* Package container implementation, provides access to background files that are stored
* inside the WallpaperEngine's pkg format
*/
class CPackage final : public CContainer {
public:
explicit CPackage (std::filesystem::path path);
[[nodiscard]] std::shared_ptr<const uint8_t[]> readFile (const std::filesystem::path& filename, uint32_t* length) const override;
protected:
/**
* Loads the current package file and loads all it's contents to memory
*/
void init ();
/**
* Reads the header from the current position and ensures it's a compatible version
*
* @param fp The file where to read from
*/
void validateHeader (FILE* fp);
/**
* Loads the files in the package into memory
*
* @param fp The file where to read from
*/
void loadFiles (FILE* fp);
/**
* Reads a size-prefixed string
*
* @param fp File to read from
*
* @return The read data, important to free it
*/
char* readSizedString (FILE* fp);
/**
* Reads a simple unsigned of 32 bits
*
* @param fp File to read from
*
* @return The read value
*/
uint32_t readInteger (FILE* fp);
private:
/** The path to the package file */
std::filesystem::path m_path {};
/** Contents of the package file */
std::map<std::string, std::unique_ptr<CFileEntry>> m_contents {};
};
} // namespace WallpaperEngine::Assets

View File

@ -1,10 +0,0 @@
#include "CPackageLoadException.h"
using namespace WallpaperEngine::Assets;
CPackageLoadException::CPackageLoadException (const std::string& filename, const std::string& extrainfo) :
m_message ("Cannot load package " + filename + ": " + extrainfo) {}
const char* CPackageLoadException::what () const noexcept {
return this->m_message.c_str ();
}

View File

@ -1,15 +0,0 @@
#pragma once
#include <exception>
#include <string>
namespace WallpaperEngine::Assets {
class CPackageLoadException final : public std::exception {
public:
explicit CPackageLoadException (const std::string& filename, const std::string& extrainfo = "");
[[nodiscard]] const char* what () const noexcept override;
private:
std::string m_message {};
};
} // namespace WallpaperEngine::Assets

View File

@ -1,42 +0,0 @@
#include <memory.h>
#include "CAssetLoadException.h"
#include "CVirtualContainer.h"
using namespace WallpaperEngine::Assets;
void CVirtualContainer::add (const std::filesystem::path& filename, const std::shared_ptr<const uint8_t[]>& contents, uint32_t length) {
this->m_virtualFiles.emplace (filename, std::make_unique<CFileEntry> (contents, length));
}
void CVirtualContainer::add (const std::filesystem::path& filename, const std::string& contents) {
// do not copy the null terminator
size_t length = contents.length ();
std::shared_ptr<uint8_t[]> copy = std::shared_ptr<uint8_t[]> (new uint8_t [length]);
memcpy (copy.get(), contents.c_str (), length);
// finally add to the container
this->add (filename, copy, length);
}
void CVirtualContainer::add (const std::filesystem::path& filename, const char* contents) {
this->add (filename, std::string (contents));
}
void CVirtualContainer::add (const std::filesystem::path& filename, const json& contents) {
this->add (filename, contents.dump ());
}
std::shared_ptr<const uint8_t[]> CVirtualContainer::readFile (const std::filesystem::path& filename, uint32_t* length) const {
const auto cur = this->m_virtualFiles.find (filename);
if (cur == this->m_virtualFiles.end ())
throw CAssetLoadException (filename, "Cannot find file in the virtual container");
if (length != nullptr)
*length = cur->second->length;
// clone original first
return cur->second->content;
}

View File

@ -1,57 +0,0 @@
#pragma once
#include <map>
#include <string>
#include <filesystem>
#include "CContainer.h"
#include "CFileEntry.h"
#include <nlohmann/json.hpp>
namespace WallpaperEngine::Assets {
using json = nlohmann::json;
/**
* Virtual container implementation, provides virtual files for the backgrounds to use
*/
class CVirtualContainer final : public CContainer {
public:
/**
* Adds a new file to the virtual container
*
* @param filename
* @param contents
* @param length
*/
void add (const std::filesystem::path& filename, const std::shared_ptr<const uint8_t[]>& contents, uint32_t length);
/**
* Adds a new file to the virtual container
*
* @param filename
* @param contents
*/
void add (const std::filesystem::path& filename, const std::string& contents);
/**
* Adds a new file to the virtual container
*
* @param filename
* @param contents
*/
void add (const std::filesystem::path& filename, const char* contents);
/**
* Adds a new file to the virtual container from a json object
* @param filename
* @param contents
*/
void add (const std::filesystem::path& filename, const json& contents);
/** @inheritdoc */
std::shared_ptr<const uint8_t[]> readFile (const std::filesystem::path& filename, uint32_t* length) const override;
private:
/** The recorded files in this virtual container */
std::map<std::string, std::unique_ptr<CFileEntry>> m_virtualFiles = {};
};
} // namespace WallpaperEngine::Assets

View File

@ -61,26 +61,24 @@ int audio_read_thread (void* arg) {
static int audio_read_data_callback (void* streamarg, uint8_t* buffer, int buffer_size) {
const auto stream = static_cast<CAudioStream*> (streamarg);
const int left = stream->getLength () - stream->getPosition ();
buffer_size = FFMIN (buffer_size, left);
stream->getBuffer ()->read (reinterpret_cast<std::istream::char_type*> (buffer), buffer_size);
memcpy (buffer, stream->getBuffer ().get() + stream->getPosition (), buffer_size);
// update position
stream->setPosition (stream->getPosition () + buffer_size);
return buffer_size;
// return read bytes only
return stream->getBuffer ()->gcount ();
}
int64_t audio_seek_data_callback (void* streamarg, int64_t offset, int whence) {
const auto stream = static_cast<CAudioStream*> (streamarg);
// this was supported before, now we don't as there's no easy way to tell length
// so returning <0 signals no support for it
if (whence & AVSEEK_SIZE)
return stream->getLength ();
return -1;
switch (whence) {
case SEEK_CUR: stream->setPosition (stream->getPosition () + offset); break;
case SEEK_SET: stream->setPosition (offset); break;
case SEEK_CUR: stream->getBuffer ()->seekg (offset, std::ios_base::cur); break;
case SEEK_SET: stream->getBuffer ()->seekg (offset, std::ios_base::beg); break;
}
return offset;
@ -91,7 +89,7 @@ CAudioStream::CAudioStream (CAudioContext& context, const std::string& filename)
this->loadCustomContent (filename.c_str ());
}
CAudioStream::CAudioStream (CAudioContext& context, std::shared_ptr<const uint8_t[]> buffer, uint32_t length) :
CAudioStream::CAudioStream (CAudioContext& context, const ReadStreamSharedPtr& buffer, uint32_t length) :
m_audioContext (context) {
// setup a custom context first
this->m_formatContext = avformat_alloc_context ();
@ -101,7 +99,6 @@ CAudioStream::CAudioStream (CAudioContext& context, std::shared_ptr<const uint8_
this->m_buffer = buffer;
this->m_length = length;
this->m_position = 0;
// setup custom io for it
this->m_formatContext->pb = avio_alloc_context (static_cast<uint8_t*> (av_malloc (4096)), 4096, 0, this,
@ -330,7 +327,7 @@ bool CAudioStream::isRepeat () const {
return this->m_repeat;
}
std::shared_ptr<const uint8_t[]> CAudioStream::getBuffer () {
ReadStreamSharedPtr& CAudioStream::getBuffer () {
return this->m_buffer;
}
@ -338,14 +335,6 @@ uint32_t CAudioStream::getLength () const {
return this->m_length;
}
uint32_t CAudioStream::getPosition () const {
return this->m_position;
}
void CAudioStream::setPosition (uint32_t current) {
this->m_position = current;
}
SDL_cond* CAudioStream::getWaitCondition () {
return this->m_queue->wait;
}

View File

@ -31,13 +31,15 @@ extern "C" {
namespace WallpaperEngine::Audio {
class CAudioContext;
using namespace WallpaperEngine::FileSystem;
/**
* Represents a playable audio stream for the audio driver
*/
class CAudioStream {
public:
CAudioStream (CAudioContext& context, const std::string& filename);
CAudioStream (CAudioContext& context, std::shared_ptr<const uint8_t[]> buffer, uint32_t length);
CAudioStream (CAudioContext& context, const ReadStreamSharedPtr& buffer, uint32_t length);
CAudioStream (CAudioContext& audioContext, AVCodecContext* context);
~CAudioStream ();
@ -88,21 +90,11 @@ class CAudioStream {
/**
* @return The file data buffer
*/
[[nodiscard]] std::shared_ptr<const uint8_t[]> getBuffer ();
[[nodiscard]] ReadStreamSharedPtr& getBuffer ();
/**
* @return The length of the file data buffer
*/
[[nodiscard]] uint32_t getLength () const;
/**
* @return The read position of the data buffer
*/
[[nodiscard]] uint32_t getPosition () const;
/**
* Updates the read position of the data buffer
*
* @param current
*/
void setPosition (uint32_t current);
/**
* @return The SDL_cond used to signal waiting for data
*/
@ -185,11 +177,9 @@ class CAudioStream {
/** The stream index for the audio being played */
int m_audioStream = NO_AUDIO_STREAM;
/** File data pointer */
std::shared_ptr<const uint8_t[]> m_buffer = nullptr;
ReadStreamSharedPtr m_buffer = nullptr;
/** The length of the file data pointer */
uint32_t m_length = 0;
/** The read position on the file data pointer */
uint32_t m_position = 0;
struct MyAVPacketList {
AVPacket* packet;

View File

@ -0,0 +1,23 @@
#pragma once
#include "Types.h"
#include "WallpaperEngine/Data/Utils/BinaryReader.h"
#include <cstdint>
#include <string>
namespace WallpaperEngine::Data::Assets {
using namespace WallpaperEngine::Data::Utils;
struct FileEntry {
std::string filename;
uint32_t offset;
uint32_t length;
};
struct Package {
BinaryReaderUniquePtr file;
FileEntryList files;
uint32_t baseOffset;
};
}

View File

@ -7,9 +7,14 @@ namespace WallpaperEngine::Data::Assets {
struct Mipmap;
struct Frame;
struct Texture;
struct Package;
struct FileEntry;
using MipmapSharedPtr = std::shared_ptr <Mipmap>;
using FrameSharedPtr = std::shared_ptr <Frame>;
using TextureUniquePtr = std::unique_ptr <Texture>;
using FileEntryUniquePtr = std::unique_ptr <FileEntry>;
using PackageUniquePtr = std::unique_ptr <Package>;
using MipmapList = std::vector <MipmapSharedPtr>;
using FileEntryList = std::vector <FileEntryUniquePtr>;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <optional>
#include "Types.h"

View File

@ -4,6 +4,7 @@
#include <memory>
#include "Types.h"
#include "WallpaperEngine/FileSystem/Container.h"
namespace WallpaperEngine::Data::Model {
/**
@ -27,7 +28,6 @@ struct Project {
bool supportsAudioProcessing;
/** All the available properties that the project defines for the user to change */
Properties properties;
/** The wallpaper this project defines */
WallpaperUniquePtr wallpaper;
/** VFS to access the project's files */

View File

@ -3,16 +3,12 @@
#include <map>
#include <vector>
#include <string>
#include <optional>
#include <memory>
#include "WallpaperEngine/Assets/CContainer.h"
namespace WallpaperEngine::Assets {
class CContainer;
namespace WallpaperEngine::FileSystem {
class Container;
}
namespace WallpaperEngine::Data::Model {
struct Project;
class Wallpaper;
@ -40,9 +36,6 @@ struct Effect;
struct EffectPass;
struct ModelStruct;
// TODO: REMOVE ONCE THESE ARE RENAMED AND MOVED
using Container = WallpaperEngine::Assets::CContainer;
using PropertySharedPtr = std::shared_ptr <Property>;
using Properties = std::map <std::string, PropertySharedPtr>;
using DynamicValueUniquePtr = std::unique_ptr <DynamicValue>;
@ -53,7 +46,7 @@ using ShaderConstantMap = std::map <std::string, UserSettingUniquePtr>;
using ProjectUniquePtr = std::unique_ptr <Project>;
using WallpaperUniquePtr = std::unique_ptr <Wallpaper>;
using ContainerUniquePtr = std::unique_ptr <Container>;
using ContainerUniquePtr = std::unique_ptr <FileSystem::Container>;
using SceneUniquePtr = std::unique_ptr <Scene>;
using WebUniquePtr = std::unique_ptr <Web>;
using VideoUniquePtr = std::unique_ptr <Video>;

View File

@ -1,15 +1,16 @@
#include "EffectParser.h"
#include "MaterialParser.h"
#include "WallpaperEngine/Data/Model/Material.h"
#include "WallpaperEngine/Data/Model/Effect.h"
#include "WallpaperEngine/Data/Model/Material.h"
#include "WallpaperEngine/Data/Model/Project.h"
#include "WallpaperEngine/FileSystem/Container.h"
using namespace WallpaperEngine::Data::Parsers;
using namespace WallpaperEngine::Data::Model;
EffectUniquePtr EffectParser::load (Project& project, const std::string& filename) {
const auto effectJson = JSON::parse (project.container->readFileAsString (filename));
const auto effectJson = JSON::parse (project.container->readString (filename));
return parse (effectJson, project);
}

View File

@ -2,12 +2,13 @@
#include "WallpaperEngine/Data/Model/Material.h"
#include "WallpaperEngine/Data/Model/Project.h"
#include "WallpaperEngine/FileSystem/Container.h"
using namespace WallpaperEngine::Data::Parsers;
using namespace WallpaperEngine::Data::Model;
MaterialUniquePtr MaterialParser::load (Project& project, const std::string& filename) {
const auto materialJson = JSON::parse (project.container->readFileAsString (filename));
const auto materialJson = JSON::parse (project.container->readString (filename));
return parse (materialJson, project, filename);
}

View File

@ -1,15 +1,16 @@
#include "ModelParser.h"
#include "MaterialParser.h"
#include "WallpaperEngine/Data/Model/Material.h"
#include "WallpaperEngine/Data/Model/Model.h"
#include "WallpaperEngine/Data/Model/Project.h"
#include "WallpaperEngine/Data/Model/Material.h"
#include "WallpaperEngine/FileSystem/Container.h"
using namespace WallpaperEngine::Data::Parsers;
using namespace WallpaperEngine::Data::Model;
ModelUniquePtr ModelParser::load (Project& project, const std::string& filename) {
const auto model = JSON::parse (project.container->readFileAsString (filename));
const auto model = JSON::parse (project.container->readString (filename));
return parse (model, project, filename);
}

View File

@ -0,0 +1,48 @@
#include "PackageParser.h"
#include "WallpaperEngine/Data/Utils/BinaryReader.h"
#include "WallpaperEngine/Logging/CLog.h"
#include "WallpaperEngine/Data/Assets/Package.h"
#include <fstream>
#include <memory>
using namespace WallpaperEngine::Data::Parsers;
using namespace WallpaperEngine::Data::Assets;
using namespace WallpaperEngine::Data::Utils;
PackageUniquePtr PackageParser::parse (ReadStreamSharedPtr stream) {
BinaryReaderUniquePtr reader = std::make_unique <BinaryReader> (std::move (stream));
if (std::string header = reader->nextSizedString (); header.starts_with ("PKGV") == false) {
sLog.exception ("Expected header to start with PKGV, got ", header);
}
auto result = std::make_unique <Package> (Package {
.file = std::move(reader),
});
result->files = parseFileList (*result->file);
result->baseOffset = result->file->base ().tellg ();
return result;
}
FileEntryList PackageParser::parseFileList (const BinaryReader& stream) {
FileEntryList result = {};
const uint32_t filesCount = stream.nextUInt32 ();
result.reserve (filesCount);
for (uint32_t i = 0; i < filesCount; i++) {
result.push_back (std::make_unique<FileEntry> (FileEntry {
.filename = stream.nextSizedString (),
.offset = stream.nextUInt32 (),
.length = stream.nextUInt32 ()
}));
}
return result;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include <iosfwd>
#include "WallpaperEngine/Data/Assets/Types.h"
#include "WallpaperEngine/Data/Utils/BinaryReader.h"
namespace WallpaperEngine::Data::Parsers {
using namespace WallpaperEngine::Data::Assets;
using namespace WallpaperEngine::Data::Utils;
class PackageParser {
public:
static PackageUniquePtr parse (ReadStreamSharedPtr stream);
private:
static FileEntryList parseFileList (const BinaryReader& stream);
};
}

View File

@ -7,6 +7,7 @@
#include "PropertyParser.h"
#include "WallpaperEngine/Data/Model/Wallpaper.h"
#include "WallpaperEngine/FileSystem/Container.h"
using namespace WallpaperEngine::Data::Parsers;

View File

@ -31,7 +31,7 @@ TextureUniquePtr TextureParser::parse (BinaryReader& file) {
result->height = file.nextUInt32 ();
// ignore some more bytes
file.nextUInt32 ();
std::ignore = file.nextUInt32 ();
file.next (magic, 9);
@ -114,13 +114,13 @@ MipmapSharedPtr TextureParser::parseMipmap (BinaryReader& file, Texture& header)
if (header.containerVersion == ContainerVersion_TEXB0004) {
// some integers that we can ignore as they only seem to affect
// the editor
file.nextUInt32 ();
file.nextUInt32 ();
std::ignore = file.nextUInt32 ();
std::ignore = file.nextUInt32 ();
// this format includes some json in the header that we might need
// to parse at some point...
result->json = file.nextNullTerminatedString ();
// last ignorable integer
file.nextUInt32 ();
std::ignore = file.nextUInt32 ();
}
result->width = file.nextUInt32 ();

View File

@ -3,6 +3,7 @@
#include "ObjectParser.h"
#include "WallpaperEngine/Data/Model/Project.h"
#include "WallpaperEngine/Data/Model/Wallpaper.h"
#include "WallpaperEngine/FileSystem/Container.h"
#include "WallpaperEngine/Logging/CLog.h"
using namespace WallpaperEngine::Data::Parsers;
@ -21,7 +22,7 @@ WallpaperUniquePtr WallpaperParser::parse (const JSON& file, Project& project) {
}
SceneUniquePtr WallpaperParser::parseScene (const JSON& file, Project& project) {
const auto scene = JSON::parse (project.container->readFileAsString (file));
const auto scene = JSON::parse (project.container->readString (file));
const auto camera = scene.require ("camera", "Scenes must have a camera section");
const auto general = scene.require ("general", "Scenes must have a general section");
const auto projection = general.require ("orthogonalprojection", "General section must have orthogonal projection info");

View File

@ -7,12 +7,12 @@
using namespace WallpaperEngine::Data::Utils;
BinaryReader::BinaryReader (std::istream& file) : m_input (file) { }
BinaryReader::BinaryReader (ReadStreamSharedPtr file) : m_input (std::move (file)) { }
uint32_t BinaryReader::nextUInt32 () {
uint32_t BinaryReader::nextUInt32 () const {
char buffer[4];
this->m_input.read (buffer, 4);
this->m_input->read (buffer, 4);
if constexpr (std::endian::native == std::endian::little) {
return (buffer [3] & 0xFF) << 24 |
@ -27,10 +27,10 @@ uint32_t BinaryReader::nextUInt32 () {
}
}
int BinaryReader::nextInt () {
int BinaryReader::nextInt () const {
char buffer[4];
this->m_input.read (buffer, 4);
this->m_input->read (buffer, 4);
if constexpr (std::endian::native == std::endian::little) {
return (buffer [3] & 0xFF) << 24 |
@ -45,17 +45,17 @@ int BinaryReader::nextInt () {
}
}
float BinaryReader::nextFloat () {
float BinaryReader::nextFloat () const {
float result;
static_assert (std::endian::native == std::endian::little, "Only little endian is supported for floats");
this->m_input.read (reinterpret_cast<char*>(&result), sizeof (result));
this->m_input->read (reinterpret_cast<char*>(&result), sizeof (result));
return result;
}
std::string BinaryReader::nextNullTerminatedString () {
std::string BinaryReader::nextNullTerminatedString () const {
std::string output;
while (const auto c = this->next ()) {
@ -65,13 +65,26 @@ std::string BinaryReader::nextNullTerminatedString () {
return output;
}
void BinaryReader::next (char* out, size_t size) {
this->m_input.read (out, size);
std::string BinaryReader::nextSizedString () const {
uint32_t length = this->nextUInt32 ();
std::string output (length, '\0');
this->m_input->read (output.data (), length);
return output;
}
char BinaryReader::next () {
void BinaryReader::next (char* out, size_t size) const {
this->m_input->read (out, size);
}
char BinaryReader::next () const {
char buffer;
this->m_input.read (&buffer, 1);
this->m_input->read (&buffer, 1);
return buffer;
}
std::istream& BinaryReader::base () const {
return *this->m_input;
}

View File

@ -2,20 +2,29 @@
#include <cstdint>
#include <iosfwd>
#include <memory>
namespace WallpaperEngine::Data::Utils {
using ReadStream = std::istream;
using ReadStreamSharedPtr = std::shared_ptr<ReadStream>;
class BinaryReader {
public:
explicit BinaryReader (std::istream& file);
explicit BinaryReader (ReadStreamSharedPtr file);
uint32_t nextUInt32 ();
int nextInt ();
float nextFloat ();
std::string nextNullTerminatedString ();
void next(char* out, size_t size);
char next ();
[[nodiscard]] uint32_t nextUInt32 () const;
[[nodiscard]] int nextInt () const;
[[nodiscard]] float nextFloat () const;
[[nodiscard]] std::string nextNullTerminatedString () const;
[[nodiscard]] std::string nextSizedString () const;
void next(char* out, size_t size) const;
[[nodiscard]] char next () const;
[[nodiscard]] std::istream& base () const;
private:
std::istream& m_input;
ReadStreamSharedPtr m_input;
};
using BinaryReaderUniquePtr = std::unique_ptr<BinaryReader>;
}

View File

@ -3,11 +3,21 @@
#include <iostream>
namespace WallpaperEngine::Data::Utils {
struct MemoryStream : std::streambuf
struct MemoryStream : std::istream, private std::streambuf
{
MemoryStream (char* p, size_t size)
MemoryStream (std::unique_ptr <char[]> buffer, const size_t size) :
std::istream (this),
m_buffer (std::move (buffer))
{
this->setg(p, p, p + size); // set start end end pointers
this->setg(
this->m_buffer.get (),
this->m_buffer.get (),
this->m_buffer.get () + size
);
}
std::unique_ptr<char[]> m_buffer;
};
using MemoryStreamSharedPtr = std::shared_ptr<MemoryStream>;
}

View File

@ -0,0 +1,87 @@
#include <filesystem>
#include <fstream>
#include <memory>
#include "Directory.h"
#include "WallpaperEngine/Assets/CAssetLoadException.h"
using namespace WallpaperEngine::FileSystem;
using namespace WallpaperEngine::FileSystem::Adapters;
ReadStreamSharedPtr DirectoryAdapter::open (const std::filesystem::path& path) const {
auto finalpath = std::filesystem::canonical(this->basepath / path);
if (finalpath.string ().find (this->basepath.string ()) != 0) {
throw std::filesystem::filesystem_error ("Cannot find file", path, std::error_code ());
}
auto status = std::filesystem::status (finalpath);
if (!std::filesystem::exists (finalpath)) {
throw std::filesystem::filesystem_error ("Cannot find file", path, std::error_code ());
}
if (!std::filesystem::is_regular_file (status)) {
throw std::filesystem::filesystem_error ("Expected file but found a directory", path, std::error_code ());
}
return std::make_shared <std::ifstream> (finalpath);
}
bool DirectoryAdapter::exists (const std::filesystem::path& path) const {
try {
auto finalpath = std::filesystem::canonical(this->basepath / path);
if (finalpath.string ().find (this->basepath.string ()) != 0) {
return false;
}
auto status = std::filesystem::status (finalpath);
if (!std::filesystem::exists (finalpath)) {
return false;
}
if (!std::filesystem::is_regular_file (status)) {
return false;
}
return true;
} catch (std::filesystem::filesystem_error&) {
return false;
}
}
std::filesystem::path DirectoryAdapter::realpath (const std::filesystem::path& path) const {
auto finalpath = std::filesystem::canonical(this->basepath / path);
if (finalpath.string ().find (this->basepath.string ()) != 0) {
throw Assets::CAssetLoadException ("Cannot find file", path);
}
return finalpath;
}
bool DirectoryFactory::handlesMountpoint (const std::filesystem::path& path) const {
auto finalpath = std::filesystem::canonical (path);
auto status = std::filesystem::status (finalpath);
return std::filesystem::exists (finalpath) && std::filesystem::is_directory (status);
}
AdapterSharedPtr DirectoryFactory::create (const std::filesystem::path& path) const {
auto finalpath = std::filesystem::canonical (path);
auto status = std::filesystem::status (finalpath);
if (!std::filesystem::exists (finalpath)) {
throw std::filesystem::filesystem_error ("Cannot find directory", path, std::error_code ());
}
if (!std::filesystem::is_directory (status)) {
throw std::filesystem::filesystem_error ("Expected directory but found a file", path, std::error_code ());
}
return std::make_unique<DirectoryAdapter> (finalpath);
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <filesystem>
#include <utility>
#include "Types.h"
namespace WallpaperEngine::FileSystem::Adapters {
struct DirectoryFactory final : Factory {
DirectoryFactory () = default;
[[nodiscard]] bool handlesMountpoint(const std::filesystem::path& path) const override;
[[nodiscard]] AdapterSharedPtr create(const std::filesystem::path& path) const override;
};
struct DirectoryAdapter final : Adapter {
explicit DirectoryAdapter (std::filesystem::path path) : basepath (std::move(path)) {}
[[nodiscard]] ReadStreamSharedPtr open (const std::filesystem::path& path) const override;
[[nodiscard]] bool exists (const std::filesystem::path& path) const override;
[[nodiscard]] std::filesystem::path realpath (const std::filesystem::path& path) const override;
const std::filesystem::path basepath;
};
}

View File

@ -0,0 +1,64 @@
#include <memory>
#include <fstream>
#include "Package.h"
#include "WallpaperEngine/Assets/CAssetLoadException.h"
#include "WallpaperEngine/Data/Parsers/PackageParser.h"
#include "WallpaperEngine/Data/Utils/BinaryReader.h"
#include "WallpaperEngine/Data/Utils/MemoryStream.h"
#include <algorithm>
using namespace WallpaperEngine::FileSystem;
using namespace WallpaperEngine::FileSystem::Adapters;
ReadStreamSharedPtr PackageAdapter::open (const std::filesystem::path& path) const {
// find the file entry
const auto it = std::ranges::find_if (this->package->files, [&path] (const auto& file) {
return file->filename == path.string ();
});
if (it == this->package->files.end ()) {
throw std::filesystem::filesystem_error ("Cannot find file", path, std::error_code ());
}
// read file into memory
auto buffer = std::make_unique <char[]> (it->get ()->length);
// go to the file's position and read into the buffer
this->package->file->base ().seekg (it->get ()->offset + this->package->baseOffset, std::ios::beg);
this->package->file->next (buffer.get (), it->get ()->length);
// create a memory stream and return that
return std::make_shared <MemoryStream> (std::move (buffer), it->get ()->length);
}
bool PackageAdapter::exists (const std::filesystem::path& path) const {
for (const auto& file : this->package->files) {
if (file->filename == path.string ()) {
return true;
}
}
return false;
}
std::filesystem::path PackageAdapter::realpath (const std::filesystem::path& path) const {
throw Assets::CAssetLoadException ("Package adapter does not support realpath", path);
}
bool PackageFactory::handlesMountpoint (const std::filesystem::path& path) const {
auto finalpath = std::filesystem::canonical (path);
auto status = std::filesystem::status (finalpath);
return std::filesystem::exists (finalpath) && std::filesystem::is_regular_file (status) && finalpath.extension () == ".pkg";
}
AdapterSharedPtr PackageFactory::create (const std::filesystem::path& path) const {
auto stream = std::make_shared <std::ifstream> (path, std::ios::binary);
auto package = Data::Parsers::PackageParser::parse (stream);
return std::make_unique <PackageAdapter> (std::move (package));
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <filesystem>
#include <utility>
#include "Types.h"
#include "WallpaperEngine/Data/Assets/Types.h"
#include "WallpaperEngine/Data/Assets/Package.h"
namespace WallpaperEngine::FileSystem::Adapters {
using namespace WallpaperEngine::Data::Assets;
struct PackageFactory final : Factory {
PackageFactory () = default;
[[nodiscard]] bool handlesMountpoint (const std::filesystem::path& path) const override;
[[nodiscard]] AdapterSharedPtr create (const std::filesystem::path& path) const override;
};
struct PackageAdapter final : Adapter {
explicit PackageAdapter (PackageUniquePtr package) : package (std::move(package)) {};
[[nodiscard]] ReadStreamSharedPtr open (const std::filesystem::path& path) const override;
[[nodiscard]] bool exists (const std::filesystem::path& path) const override;
[[nodiscard]] std::filesystem::path realpath (const std::filesystem::path& path) const override;
PackageUniquePtr package;
};
}

View File

@ -0,0 +1,28 @@
#pragma once
#include <filesystem>
#include "WallpaperEngine/Data/Utils/BinaryReader.h"
namespace WallpaperEngine::FileSystem::Adapters {
using namespace WallpaperEngine::Data::Utils;
struct Adapter {
Adapter () = default;
virtual ~Adapter () = default;
[[nodiscard]] virtual ReadStreamSharedPtr open (const std::filesystem::path& path) const = 0;
[[nodiscard]] virtual bool exists (const std::filesystem::path& path) const = 0;
[[nodiscard]] virtual std::filesystem::path realpath (const std::filesystem::path& path) const = 0;
};
using AdapterSharedPtr = std::shared_ptr<Adapter>;
struct Factory {
Factory () = default;
virtual ~Factory () = default;
[[nodiscard]] virtual bool handlesMountpoint (const std::filesystem::path& path) const = 0;
[[nodiscard]] virtual AdapterSharedPtr create (const std::filesystem::path& path) const = 0;
};
using FactoryUniquePtr = std::unique_ptr<Factory>;
} // namespace WallpaperEngine::FileSystem::Adapters

View File

@ -0,0 +1,59 @@
#include "Virtual.h"
#include "WallpaperEngine/Assets/CAssetLoadException.h"
#include <cstring>
using namespace WallpaperEngine::FileSystem;
using namespace WallpaperEngine::FileSystem::Adapters;
ReadStreamSharedPtr VirtualAdapter::open (const std::filesystem::path& path) const {
const auto file = this->files.find (path);
if (file == this->files.end ()) {
throw std::filesystem::filesystem_error ("Cannot find file", path, std::error_code ());
}
return file->second;
}
bool VirtualAdapter::exists (const std::filesystem::path& path) const {
return this->files.contains (path);
}
std::filesystem::path VirtualAdapter::realpath (const std::filesystem::path& path) const {
throw Assets::CAssetLoadException ("Virtual adapter does not support realpath", path);
}
void VirtualAdapter::add (const std::filesystem::path& path, const char* data) {
size_t length = strlen (data);
auto buffer = std::make_unique <char[]> (length);
std::memcpy (buffer.get (), data, length);
this->add (path, std::make_shared <MemoryStream> (std::move (buffer), length));
}
void VirtualAdapter::add (const std::filesystem::path& path, const JSON& data) {
this->add (path, data.dump ());
}
void VirtualAdapter::add (const std::filesystem::path& path, const std::string& data) {
auto buffer = std::make_unique <char[]> (data.size ());
std::memcpy (buffer.get (), data.data (), data.size ());
this->add (path, std::make_shared <MemoryStream> (std::move (buffer), data.size ()));
}
void VirtualAdapter::add (const std::filesystem::path& path, MemoryStreamSharedPtr stream) {
this->files.insert_or_assign (path, stream);
}
bool VirtualFactory::handlesMountpoint (const std::filesystem::path& path) const {
return path.string () == "virtual";
}
AdapterSharedPtr VirtualFactory::create (const std::filesystem::path& path) const {
return std::make_unique<VirtualAdapter> ();
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <filesystem>
#include <utility>
#include "Types.h"
#include "WallpaperEngine/Data/Utils/MemoryStream.h"
#include "WallpaperEngine/Data/JSON.h"
#include <map>
namespace WallpaperEngine::FileSystem::Adapters {
using JSON = WallpaperEngine::Data::JSON::JSON;
struct VirtualFactory final : Factory {
[[nodiscard]] bool handlesMountpoint (const std::filesystem::path& path) const override;
[[nodiscard]] AdapterSharedPtr create (const std::filesystem::path& path) const override;
};
struct VirtualAdapter final : Adapter {
[[nodiscard]] ReadStreamSharedPtr open (const std::filesystem::path& path) const override;
[[nodiscard]] bool exists (const std::filesystem::path& path) const override;
[[nodiscard]] std::filesystem::path realpath (const std::filesystem::path& path) const override;
void add (const std::filesystem::path& path, const char* data);
void add (const std::filesystem::path& path, const JSON& contents);
void add (const std::filesystem::path& path, const std::string& data);
void add (const std::filesystem::path& path, MemoryStreamSharedPtr stream);
std::map <std::filesystem::path, MemoryStreamSharedPtr> files;
};
}

View File

@ -0,0 +1,126 @@
#include <map>
#include <memory>
#include "Container.h"
#include "Adapters/Directory.h"
#include "Adapters/Package.h"
#include "Adapters/Types.h"
#include "Adapters/Virtual.h"
#include "WallpaperEngine/Assets/CAssetLoadException.h"
#include "WallpaperEngine/Logging/CLog.h"
using namespace WallpaperEngine::FileSystem;
using namespace WallpaperEngine::FileSystem::Adapters;
/**
* Normalizes a file path to get rid of relative stuff as most as possible
* This is not a security measure but helps keep adapters that do not really have an actual filesystem
* behind to trust the input data without much validation
*
* Normalization is handled by going up a level on ".." when there's a previous level
* or keeping it when there's none, this will most likely not be a valid path, but
* the filesystem might resolve it into a file that's inside it's root, so this has to be taken into account
*
* @param input_path The path to normalize
* @return The normalized path
*/
std::filesystem::path normalize_path(const std::filesystem::path& input_path) {
std::filesystem::path result;
for (const auto& part : input_path) {
std::string part_str = part.string();
if (part_str == ".") {
// Skip
} else if (part_str == "..") {
// Go up one level if possible
if (!result.empty() && *--result.end() != "..") {
result = result.parent_path();
} else {
// If we're already at root or have ".." segments,
// keep the ".." (for relative paths)
result /= part;
}
} else {
// Add regular segment
result /= part;
}
}
return result;
}
Container::Container () {
// register all available factories
this->m_factories.push_back (std::make_unique<VirtualFactory> ());
this->m_factories.push_back (std::make_unique<PackageFactory> ());
this->m_factories.push_back (std::make_unique<DirectoryFactory> ());
// TODO: FIND A BETTER WAY OF MOUNTING THE VIRTUAL FILESYSTEM
this->m_vfs = std::make_shared<VirtualAdapter> ();
this->m_mountpoints.emplace_back ("/", this->m_vfs);
// mount the current directory as root
this->mount (std::filesystem::current_path (), "/");
}
ReadStreamSharedPtr Container::read (const std::filesystem::path& path) const {
std::filesystem::path normalized = normalize_path (path);
return this->resolveAdapterForFile (path).open (normalized);
}
std::string Container::readString (const std::filesystem::path& path) const {
const auto stream = this->read (path);
std::stringstream buffer;
buffer << stream->rdbuf ();
return buffer.str ();
}
std::filesystem::path Container::realpath (const std::filesystem::path& path) const {
std::filesystem::path normalized = normalize_path (path);
return this->resolveAdapterForFile (path).realpath (normalized);
}
AdapterSharedPtr Container::mount (const std::filesystem::path& path, const std::filesystem::path& mountPoint) {
// check if any adapter can handle the path
for (const auto& factory : this->m_factories) {
if (factory->handlesMountpoint (path) == false) {
continue;
}
return this->m_mountpoints.emplace_back (mountPoint, factory->create (path)).second;
}
sLog.exception("The specified mount (", path, ") cannot be handled by any of the filesystem adapters");
}
VirtualAdapter& Container::getVFS () const {
return *this->m_vfs;
}
Adapter& Container::resolveAdapterForFile (const std::filesystem::path& path) const {
std::filesystem::path normalized = normalize_path (path);
for (const auto& [root, adapter] : this->m_mountpoints) {
if (normalized.string().starts_with (root.string()) == false) {
continue;
}
std::filesystem::path relative = normalized.string().substr (root.string().length());
if (adapter->exists (relative) == false) {
continue;
}
return *adapter;
}
if (normalized.string().starts_with ("/") == false) {
// try resolving as absolute, just in case it's relative to the root
return this->resolveAdapterForFile ("/" + normalized.string());
}
throw Assets::CAssetLoadException ("Cannot find requested file ", path);
}

View File

@ -0,0 +1,70 @@
#pragma once
#include "Adapters/Types.h"
#include "Adapters/Virtual.h"
#include "WallpaperEngine/Data/Utils/BinaryReader.h"
#include <filesystem>
namespace WallpaperEngine::FileSystem {
using namespace WallpaperEngine::Data::Utils;
using namespace WallpaperEngine::FileSystem::Adapters;
class Container {
public:
Container ();
~Container () = default;
/**
* Opens the given file in read mode
*
* @param path The file to open
* @return The input stream to read file's data off of
*/
[[nodiscard]] ReadStreamSharedPtr read (const std::filesystem::path& path) const;
/**
* Opens the given file and reads it completely into memory
*
* @param path The file to open
* @return The file's contents as std::string
*/
[[nodiscard]] std::string readString (const std::filesystem::path& path) const;
/**
* Tries to resolve the given file into an absolute, real, filesystem path
* to be used as info for other tools that might require it (like MPV)
*
* @param path The path to resolve to a real file
* @return The full public, absolute path to the given file
*/
[[nodiscard]] std::filesystem::path realpath (const std::filesystem::path& path) const;
/**
*
* @param path Base of the mountpoint
* @param mountPoint Where in the VFS to mount it
*/
AdapterSharedPtr mount (const std::filesystem::path& path, const std::filesystem::path& mountPoint);
/**
* @return Access to the virtual file system adapter in this container instance
*/
VirtualAdapter& getVFS () const;
private:
/**
* Searches for an adapter to handle the given file
*
* @param path The path to the file
* @return The adapter handling the file
*/
Adapter& resolveAdapterForFile (const std::filesystem::path& path) const;
/** The factories available for this container */
std::vector<FactoryUniquePtr> m_factories;
/** Mountpoints on this container */
std::vector<std::pair<std::filesystem::path, AdapterSharedPtr>> m_mountpoints;
/** Virtual file system adapter */
std::shared_ptr<VirtualAdapter> m_vfs;
};
}

View File

@ -15,7 +15,7 @@ Wallpapers::CScene& CObject::getScene () const {
return this->m_scene;
}
const CContainer& CObject::getContainer () const {
const Container& CObject::getContainer () const {
return this->getScene ().getContainer ();
}

View File

@ -36,7 +36,7 @@ class CObject : public Helpers::CContextAware {
virtual void render () = 0;
[[nodiscard]] Wallpapers::CScene& getScene () const;
[[nodiscard]] const CContainer& getContainer () const;
[[nodiscard]] const Container& getContainer () const;
[[nodiscard]] int getId () const;
protected:

View File

@ -1,12 +1,17 @@
#include "CTextureCache.h"
#include "WallpaperEngine/FileSystem/Container.h"
#include "WallpaperEngine/Assets/CAssetLoadException.h"
#include "WallpaperEngine/Assets/CTexture.h"
#include "WallpaperEngine/Render/Helpers/CContextAware.h"
#include "WallpaperEngine/Data/Model/Project.h"
#include "WallpaperEngine/Data/Parsers/TextureParser.h"
using namespace WallpaperEngine::Render;
using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::FileSystem;
using namespace WallpaperEngine::Data::Parsers;
CTextureCache::CTextureCache (CRenderContext& context) : Helpers::CContextAware (context) {}
@ -16,10 +21,17 @@ std::shared_ptr<const ITexture> CTextureCache::resolve (const std::string& filen
if (found != this->m_textureCache.end ())
return found->second;
auto finalFilename = std::filesystem::path("materials") / filename;
finalFilename.replace_extension ("tex");
// search for the texture in all the different containers just in case
for (const auto& [name, project] : this->getContext ().getApp ().getBackgrounds ()) {
try {
std::shared_ptr<const ITexture> texture = project->container->readTexture (filename);
auto contents = project->container->read (finalFilename);
auto stream = BinaryReader (contents);
auto parsedTexture = TextureParser::parse (stream);
auto texture = std::make_shared <CTexture> (std::move (parsedTexture));
this->store (filename, texture);

View File

@ -45,7 +45,7 @@ CWallpaper::CWallpaper (
CWallpaper::~CWallpaper () = default;
const CContainer& CWallpaper::getContainer () const {
const Container& CWallpaper::getContainer () const {
return *this->m_wallpaperData.project.container;
}

View File

@ -3,7 +3,6 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "WallpaperEngine/Assets/CContainer.h"
#include "WallpaperEngine/Audio/CAudioContext.h"
#include "WallpaperEngine/Render/CFBO.h"
@ -27,6 +26,7 @@ class CContextAware;
using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Audio;
using namespace WallpaperEngine::Data::Model;
using namespace WallpaperEngine::FileSystem;
class CWallpaper : public Helpers::CContextAware, public CFBOProvider {
public:
@ -65,7 +65,7 @@ class CWallpaper : public Helpers::CContextAware, public CFBOProvider {
/**
* @return The container to resolve files for this wallpaper
*/
[[nodiscard]] const CContainer& getContainer () const;
[[nodiscard]] const Container& getContainer () const;
/**
* @return The current audio context for this wallpaper

View File

@ -2,6 +2,8 @@
#include "CSound.h"
#include "WallpaperEngine/FileSystem/Container.h"
using namespace WallpaperEngine::Render::Objects;
CSound::CSound (Wallpapers::CScene& scene, const Sound& sound) :
@ -16,21 +18,17 @@ CSound::~CSound() {
for (const auto& stream : this->m_audioStreams) {
delete stream;
}
this->m_soundBuffer.clear ();
}
void CSound::load () {
for (const auto& cur : this->m_sound.sounds) {
uint32_t filesize = 0;
std::shared_ptr<const uint8_t[]> filebuffer = this->getContainer ().readFile (cur, &filesize);
auto filebuffer = this->getContainer ().read (cur);
auto stream = new Audio::CAudioStream (this->getScene ().getAudioContext (), filebuffer, filesize);
stream->setRepeat (this->m_sound.playbackmode.has_value() && this->m_sound.playbackmode == "loop");
this->m_audioStreams.push_back (stream);
this->m_soundBuffer.push_back (filebuffer);
// add the stream to the context so it can be played
this->getScene ().getAudioContext ().addStream (stream);

View File

@ -23,7 +23,6 @@ class CSound final : public CObject {
void load ();
private:
std::vector<std::shared_ptr<const uint8_t[]>> m_soundBuffer = {};
std::vector<Audio::CAudioStream*> m_audioStreams = {};
const Sound& m_sound;

View File

@ -9,21 +9,64 @@
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
#include "CGLSLContext.h"
#include "WallpaperEngine/Assets/CAssetLoadException.h"
#include "WallpaperEngine/FileSystem/Container.h"
using namespace WallpaperEngine::Assets;
namespace WallpaperEngine::Render::Shaders {
// TODO: MOVE THIS INTO AN ASSET RESOLVER OR SOMETHING SIMILAR AS IT DOESN'T REALLY BELONG HERE BUT GETS THE CHANGESET OUT
std::string readShader (const std::filesystem::path& filename, const Container& container) {
std::filesystem::path shader = filename;
auto it = shader.begin ();
// detect workshop shaders and check if there's a
if (*it++ == "workshop") {
const std::filesystem::path workshopId = *it++;
if (++it != shader.end ()) {
const std::filesystem::path& shaderfile = *it;
try {
shader = std::filesystem::path ("zcompat") / "scene" / "shaders" / workshopId / shaderfile;
// replace the old path with the new one
std::string contents = container.readString (shader);
sLog.out ("Replaced ", filename, " with compat ", shader);
return contents;
} catch (CAssetLoadException&) {
}
}
}
return container.readString ("shaders" / filename);
}
std::string readVertex (const std::filesystem::path& filename, const Container& container) {
std::filesystem::path shader = filename;
shader.replace_extension (".vert");
return readShader (shader, container);
}
std::string readFragment (const std::filesystem::path& filename, const Container& container) {
std::filesystem::path shader = filename;
shader.replace_extension (".frag");
return readShader (shader, container);
}
CShader::CShader (
const CContainer& container, std::string filename,
const Container& container, std::string filename,
const ComboMap& combos, const ComboMap& overrideCombos,
const TextureMap& textures, const TextureMap& overrideTextures,
const ShaderConstantMap& constants
) :
m_vertex (
CGLSLContext::UnitType_Vertex, filename, container.readVertexShader (filename),
CGLSLContext::UnitType_Vertex, filename, readVertex (filename, container),
container, constants, textures, overrideTextures, combos, overrideCombos),
m_fragment (
CGLSLContext::UnitType_Fragment, filename, container.readFragmentShader (filename),
CGLSLContext::UnitType_Fragment, filename, readFragment (filename, container),
container, constants, textures, overrideTextures, combos, overrideCombos),
m_file (std::move (filename)),
m_combos (combos),

View File

@ -4,7 +4,6 @@
#include <map>
#include <vector>
#include "WallpaperEngine/Assets/CContainer.h"
#include "WallpaperEngine/Assets/ITexture.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
@ -42,7 +41,7 @@ class CShader {
* @param recursive Whether the compiler should add base definitions or not
*/
CShader (
const CContainer& container, std::string filename,
const Container& container, std::string filename,
const ComboMap& combos, const ComboMap& overrideCombos,
const TextureMap& textures, const TextureMap& overrideTextures,
const ShaderConstantMap& constants);

View File

@ -16,6 +16,7 @@
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.h"
#include "WallpaperEngine/Data/Builders/VectorBuilder.h"
#include "WallpaperEngine/FileSystem/Container.h"
#define SHADER_HEADER(filename) "#version 330\n" \
"// ======================================================\n" \
@ -52,7 +53,7 @@ using namespace WallpaperEngine::Data::Builders;
using namespace WallpaperEngine::Render::Shaders;
CShaderUnit::CShaderUnit (
CGLSLContext::UnitType type, std::string file, std::string content, const CContainer& container,
CGLSLContext::UnitType type, std::string file, std::string content, const Container& container,
const ShaderConstantMap& constants, const TextureMap& passTextures, const TextureMap& overrideTextures,
const ComboMap& combos, const ComboMap& overrideCombos
) :
@ -151,7 +152,8 @@ void CShaderUnit::preprocessIncludes () {
content += "// begin of include from file ";
content += filename;
content += "\n";
content += this->m_container.readIncludeShader (filename);
// TODO: MOVE SHADER PATH FROM HERE TO SOMEWHERE LIKE AN ASSET RESOLVER OR SOMETHING LIKE THAT
content += this->m_container.readString (std::filesystem::path("shaders") / filename);
content += "\n// end of included from file ";
content += filename;
content += "\n";
@ -190,7 +192,8 @@ void CShaderUnit::preprocessIncludes () {
content = "// begin of include from file ";
content += filename;
content += "\n";
content += this->m_container.readIncludeShader (filename);
// TODO: MOVE SHADER PATH FROM HERE TO SOMEWHERE LIKE AN ASSET RESOLVER OR SOMETHING LIKE THAT
content += this->m_container.readString (std::filesystem::path("shaders") / filename);
content += "\n// end of included from file ";
content += filename;
content += "\n";

View File

@ -5,7 +5,6 @@
#include <string>
#include "CGLSLContext.h"
#include "WallpaperEngine/Assets/CContainer.h"
#include "WallpaperEngine/Data/JSON.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
#include "nlohmann/json.hpp"
@ -14,7 +13,7 @@
namespace WallpaperEngine::Render::Shaders {
using JSON = WallpaperEngine::Data::JSON::JSON;
using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::FileSystem;
using namespace WallpaperEngine::Data::Model;
/**
@ -23,7 +22,7 @@ using namespace WallpaperEngine::Data::Model;
class CShaderUnit {
public:
CShaderUnit (
CGLSLContext::UnitType type, std::string file, std::string content, const CContainer& container,
CGLSLContext::UnitType type, std::string file, std::string content, const Container& container,
const ShaderConstantMap& constants, const TextureMap& passTextures,
const TextureMap& overrideTextures, const ComboMap& combos, const ComboMap& overrideCombos);
~CShaderUnit () = default;
@ -159,6 +158,6 @@ class CShaderUnit {
/**
* The container to source files from
*/
const CContainer& m_container;
const Container& m_container;
};
}

View File

@ -57,7 +57,7 @@ CVideo::CVideo (
sLog.exception ("Failed to initialize MPV's GL context");
const std::filesystem::path videopath =
this->getVideo ().project.container->resolveRealFile (this->getVideo ().filename);
this->getVideo ().project.container->realpath (this->getVideo ().filename);
// build the path to the video file
const char* command [] = {"loadfile", videopath.c_str (), nullptr};

View File

@ -48,7 +48,7 @@ bool CWPSchemeHandler::Open(CefRefPtr<CefRequest> request,
this->m_mimeType = mime;
}
this->m_contents = this->m_container.readFile (file, &this->m_filesize);
this->m_contents = this->m_container.read (file);
callback->Continue ();
} catch (CAssetLoadException&) {
#if !NDEBUG
@ -77,7 +77,8 @@ void CWPSchemeHandler::GetResponseHeaders(CefRefPtr<CefResponse> response,
response->SetMimeType (this->m_mimeType);
response->SetStatus (200);
response_length = this->m_filesize;
// signals an unknown-length file
response_length = -1;
}
void CWPSchemeHandler::Cancel () {
@ -90,14 +91,18 @@ bool CWPSchemeHandler::Read(void* data_out, int bytes_to_read, int& bytes_read,
bytes_read = 0;
if (this->m_contents && this->m_offset < this->m_filesize) {
int bytes_to_transfer = std::min (bytes_to_read, static_cast <int> (this->m_filesize - this->m_offset));
memcpy (data_out, &this->m_contents [this->m_offset], bytes_to_transfer);
this->m_offset += bytes_read = bytes_to_transfer;
return true;
if (this->m_contents->eof ()) {
return false;
}
try {
this->m_contents->read (static_cast<std::istream::char_type*> (data_out), bytes_to_read);
} catch (std::ios::failure&) {
bytes_read = -1;
return false;
}
bytes_read = this->m_contents->gcount ();
return true;
}

View File

@ -2,19 +2,18 @@
#include <string>
#include "WallpaperEngine/FileSystem/Container.h"
#include "include/cef_resource_handler.h"
#include "include/wrapper/cef_helpers.h"
namespace WallpaperEngine::Assets {
class CContainer;
}
namespace WallpaperEngine::Data::Model {
class Project;
struct Project;
}
namespace WallpaperEngine::WebBrowser::CEF {
using namespace WallpaperEngine::FileSystem;
using namespace WallpaperEngine::Data::Model;
/**
@ -40,11 +39,9 @@ class CWPSchemeHandler : public CefResourceHandler {
private:
const Project& m_project;
const Assets::CContainer& m_container;
std::shared_ptr<const uint8_t[]> m_contents = nullptr;
uint32_t m_filesize = 0;
std::string m_mimeType = "";
uint32_t m_offset = 0;
const Container& m_container;
ReadStreamSharedPtr m_contents = nullptr;
std::string m_mimeType;
IMPLEMENT_REFCOUNTING(CWPSchemeHandler);