mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-09-14 13:56:48 +08:00
refactor: overhaul the filesystem layer
This commit is contained in:
parent
822891008d
commit
2d6675db0b
@ -267,23 +267,21 @@ add_executable(
|
|||||||
src/WallpaperEngine/Application/CWallpaperApplication.cpp
|
src/WallpaperEngine/Application/CWallpaperApplication.cpp
|
||||||
src/WallpaperEngine/Application/CWallpaperApplication.h
|
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/ITexture.h
|
||||||
src/WallpaperEngine/Assets/CTexture.h
|
src/WallpaperEngine/Assets/CTexture.h
|
||||||
src/WallpaperEngine/Assets/CTexture.cpp
|
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.cpp
|
||||||
src/WallpaperEngine/Audio/Drivers/Recorders/CPulseAudioPlaybackRecorder.h
|
src/WallpaperEngine/Audio/Drivers/Recorders/CPulseAudioPlaybackRecorder.h
|
||||||
@ -404,6 +402,7 @@ add_executable(
|
|||||||
|
|
||||||
src/WallpaperEngine/Data/Assets/Types.h
|
src/WallpaperEngine/Data/Assets/Types.h
|
||||||
src/WallpaperEngine/Data/Assets/Texture.h
|
src/WallpaperEngine/Data/Assets/Texture.h
|
||||||
|
src/WallpaperEngine/Data/Assets/Package.h
|
||||||
src/WallpaperEngine/Data/Model/Types.h
|
src/WallpaperEngine/Data/Model/Types.h
|
||||||
src/WallpaperEngine/Data/Model/Project.h
|
src/WallpaperEngine/Data/Model/Project.h
|
||||||
src/WallpaperEngine/Data/Model/Wallpaper.h
|
src/WallpaperEngine/Data/Model/Wallpaper.h
|
||||||
@ -437,6 +436,8 @@ add_executable(
|
|||||||
src/WallpaperEngine/Data/Parsers/ModelParser.h
|
src/WallpaperEngine/Data/Parsers/ModelParser.h
|
||||||
src/WallpaperEngine/Data/Parsers/ShaderConstantParser.cpp
|
src/WallpaperEngine/Data/Parsers/ShaderConstantParser.cpp
|
||||||
src/WallpaperEngine/Data/Parsers/ShaderConstantParser.h
|
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.cpp
|
||||||
src/WallpaperEngine/Data/Parsers/PropertyParser.h
|
src/WallpaperEngine/Data/Parsers/PropertyParser.h
|
||||||
src/WallpaperEngine/Data/Parsers/TextureParser.cpp
|
src/WallpaperEngine/Data/Parsers/TextureParser.cpp
|
||||||
@ -450,7 +451,11 @@ add_executable(
|
|||||||
|
|
||||||
${WAYLAND_SOURCES}
|
${WAYLAND_SOURCES}
|
||||||
${X11_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
|
target_link_libraries (linux-wallpaperengine PUBLIC
|
||||||
${OPENGL_LIBRARIES}
|
${OPENGL_LIBRARIES}
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
#include "Steam/FileSystem/FileSystem.h"
|
#include "Steam/FileSystem/FileSystem.h"
|
||||||
#include "WallpaperEngine/Application/CApplicationState.h"
|
#include "WallpaperEngine/Application/CApplicationState.h"
|
||||||
#include "WallpaperEngine/Assets/CAssetLoadException.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/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h"
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
#include "WallpaperEngine/Logging/CLog.h"
|
#include "WallpaperEngine/Logging/CLog.h"
|
||||||
#include "WallpaperEngine/Render/CRenderContext.h"
|
#include "WallpaperEngine/Render/CRenderContext.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/CVideoFactories.h"
|
#include "WallpaperEngine/Render/Drivers/CVideoFactories.h"
|
||||||
@ -32,6 +31,7 @@ float g_Daytime;
|
|||||||
|
|
||||||
using namespace WallpaperEngine::Application;
|
using namespace WallpaperEngine::Application;
|
||||||
using namespace WallpaperEngine::Data::Model;
|
using namespace WallpaperEngine::Data::Model;
|
||||||
|
using namespace WallpaperEngine::FileSystem;
|
||||||
|
|
||||||
CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
|
CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
|
||||||
m_context (context) {
|
m_context (context) {
|
||||||
@ -41,21 +41,30 @@ CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg) const {
|
ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg) const {
|
||||||
auto container = std::make_unique <CCombinedContainer> ();
|
auto container = std::make_unique <Container> ();
|
||||||
const std::filesystem::path basepath = bg;
|
|
||||||
|
|
||||||
container->add (std::make_unique<CDirectory> (basepath));
|
std::filesystem::path path (bg);
|
||||||
container->addPkg (basepath / "scene.pkg");
|
|
||||||
container->addPkg (basepath / "gifscene.pkg");
|
container->mount (path, "/");
|
||||||
|
try {
|
||||||
|
container->mount (path / "scene.pkg", "/");
|
||||||
|
} catch (std::runtime_error&) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
container->add (std::make_unique <CDirectory> (this->m_context.settings.general.assets));
|
container->mount (path / "gifscene.pkg", "/");
|
||||||
} catch (CAssetLoadException&) {
|
} 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);
|
sLog.exception ("Cannot find a valid assets folder, resolved to ", this->m_context.settings.general.assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this somewhere else?
|
auto& vfs = container->getVFS ();
|
||||||
auto virtualContainer = std::make_unique <CVirtualContainer> ();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Had to get a little creative with the effects to achieve the same bloom effect without any custom code
|
// 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 the effect file for screen bloom
|
||||||
|
|
||||||
// add some model for the image element even if it's going to waste rendering cycles
|
// add some model for the image element even if it's going to waste rendering cycles
|
||||||
virtualContainer->add (
|
vfs.add (
|
||||||
"effects/wpenginelinux/bloomeffect.json",
|
"effects/wpenginelinux/bloomeffect.json",
|
||||||
{
|
{
|
||||||
{"name", "camerabloom_wpengine_linux"},
|
{"name", "camerabloom_wpengine_linux"},
|
||||||
{"group", "wpengine_linux_camera"},
|
{"group", "wpengine_linux_camera"},
|
||||||
{"dependencies", json::array ()},
|
{"dependencies", JSON::array ()},
|
||||||
{"passes",
|
{"passes",
|
||||||
json::array (
|
JSON::array (
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{"material", "materials/util/downsample_quarter_bloom.json"},
|
{"material", "materials/util/downsample_quarter_bloom.json"},
|
||||||
{"target", "_rt_4FrameBuffer"},
|
{"target", "_rt_4FrameBuffer"},
|
||||||
{
|
{
|
||||||
"bind",
|
"bind",
|
||||||
json::array (
|
JSON::array (
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{"name", "_rt_FullFrameBuffer"},
|
{"name", "_rt_FullFrameBuffer"},
|
||||||
@ -95,7 +104,7 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
|
|||||||
{"target", "_rt_8FrameBuffer"},
|
{"target", "_rt_8FrameBuffer"},
|
||||||
{
|
{
|
||||||
"bind",
|
"bind",
|
||||||
json::array (
|
JSON::array (
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{"name", "_rt_4FrameBuffer"},
|
{"name", "_rt_4FrameBuffer"},
|
||||||
@ -110,7 +119,7 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
|
|||||||
{"target", "_rt_Bloom"},
|
{"target", "_rt_Bloom"},
|
||||||
{
|
{
|
||||||
"bind",
|
"bind",
|
||||||
json::array (
|
JSON::array (
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{"name", "_rt_8FrameBuffer"},
|
{"name", "_rt_8FrameBuffer"},
|
||||||
@ -125,7 +134,7 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
|
|||||||
{"target", "_rt_FullFrameBuffer"},
|
{"target", "_rt_FullFrameBuffer"},
|
||||||
{
|
{
|
||||||
"bind",
|
"bind",
|
||||||
json::array (
|
JSON::array (
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{"name", "_rt_imageLayerComposite_-1_a"},
|
{"name", "_rt_imageLayerComposite_-1_a"},
|
||||||
@ -145,17 +154,17 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
virtualContainer->add (
|
vfs.add (
|
||||||
"models/wpenginelinux.json",
|
"models/wpenginelinux.json",
|
||||||
{
|
{
|
||||||
{"material","materials/wpenginelinux.json"}
|
{"material","materials/wpenginelinux.json"}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
virtualContainer->add(
|
vfs.add(
|
||||||
"materials/wpenginelinux.json",
|
"materials/wpenginelinux.json",
|
||||||
{
|
{
|
||||||
{"passes", json::array (
|
{"passes", JSON::array (
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{"blending", "normal"},
|
{"blending", "normal"},
|
||||||
@ -163,13 +172,13 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
|
|||||||
{"depthtest", "disabled"},
|
{"depthtest", "disabled"},
|
||||||
{"depthwrite", "disabled"},
|
{"depthwrite", "disabled"},
|
||||||
{"shader", "genericimage2"},
|
{"shader", "genericimage2"},
|
||||||
{"textures", json::array ({"_rt_FullFrameBuffer"})}
|
{"textures", JSON::array ({"_rt_FullFrameBuffer"})}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)}}
|
)}}
|
||||||
);
|
);
|
||||||
|
|
||||||
virtualContainer->add(
|
vfs.add(
|
||||||
"shaders/commands/copy.frag",
|
"shaders/commands/copy.frag",
|
||||||
"uniform sampler2D g_Texture0;\n"
|
"uniform sampler2D g_Texture0;\n"
|
||||||
"in vec2 v_TexCoord;\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"
|
"out_FragColor = texture (g_Texture0, v_TexCoord);\n"
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
virtualContainer->add(
|
vfs.add(
|
||||||
"shaders/commands/copy.vert",
|
"shaders/commands/copy.vert",
|
||||||
"in vec3 a_Position;\n"
|
"in vec3 a_Position;\n"
|
||||||
"in vec2 a_TexCoord;\n"
|
"in vec2 a_TexCoord;\n"
|
||||||
@ -188,8 +197,6 @@ ContainerUniquePtr CWallpaperApplication::setupContainer (const std::string& bg)
|
|||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
container->add (std::move(virtualContainer));
|
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +219,7 @@ void CWallpaperApplication::loadBackgrounds () {
|
|||||||
|
|
||||||
ProjectUniquePtr CWallpaperApplication::loadBackground (const std::string& bg) {
|
ProjectUniquePtr CWallpaperApplication::loadBackground (const std::string& bg) {
|
||||||
auto container = this->setupContainer (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));
|
return WallpaperEngine::Data::Parsers::ProjectParser::parse (json, std::move(container));
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "WallpaperEngine/Application/CApplicationContext.h"
|
#include "WallpaperEngine/Application/CApplicationContext.h"
|
||||||
|
|
||||||
#include "WallpaperEngine/Assets/CCombinedContainer.h"
|
|
||||||
|
|
||||||
#include "WallpaperEngine/Render/CRenderContext.h"
|
#include "WallpaperEngine/Render/CRenderContext.h"
|
||||||
#include "WallpaperEngine/Render/CWallpaper.h"
|
#include "WallpaperEngine/Render/CWallpaper.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/CGLFWOpenGLDriver.h"
|
#include "WallpaperEngine/Render/Drivers/CGLFWOpenGLDriver.h"
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
// TODO: REWRITE THIS ONE TO MAKE MORE SENSE, IT REALLY MEANS "FILE-RELATED EXCEPTION"
|
||||||
namespace WallpaperEngine::Assets {
|
namespace WallpaperEngine::Assets {
|
||||||
class CAssetLoadException final : public std::exception {
|
class CAssetLoadException final : public std::exception {
|
||||||
public:
|
public:
|
||||||
|
@ -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");
|
|
||||||
}
|
|
@ -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
|
|
@ -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
|
|
||||||
};
|
|
||||||
}
|
|
@ -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
|
|
@ -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 ());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
@ -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 ();
|
|
||||||
}
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
@ -61,26 +61,24 @@ int audio_read_thread (void* arg) {
|
|||||||
|
|
||||||
static int audio_read_data_callback (void* streamarg, uint8_t* buffer, int buffer_size) {
|
static int audio_read_data_callback (void* streamarg, uint8_t* buffer, int buffer_size) {
|
||||||
const auto stream = static_cast<CAudioStream*> (streamarg);
|
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);
|
// return read bytes only
|
||||||
// update position
|
return stream->getBuffer ()->gcount ();
|
||||||
stream->setPosition (stream->getPosition () + buffer_size);
|
|
||||||
|
|
||||||
return buffer_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t audio_seek_data_callback (void* streamarg, int64_t offset, int whence) {
|
int64_t audio_seek_data_callback (void* streamarg, int64_t offset, int whence) {
|
||||||
const auto stream = static_cast<CAudioStream*> (streamarg);
|
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)
|
if (whence & AVSEEK_SIZE)
|
||||||
return stream->getLength ();
|
return -1;
|
||||||
|
|
||||||
switch (whence) {
|
switch (whence) {
|
||||||
case SEEK_CUR: stream->setPosition (stream->getPosition () + offset); break;
|
case SEEK_CUR: stream->getBuffer ()->seekg (offset, std::ios_base::cur); break;
|
||||||
case SEEK_SET: stream->setPosition (offset); break;
|
case SEEK_SET: stream->getBuffer ()->seekg (offset, std::ios_base::beg); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
@ -91,7 +89,7 @@ CAudioStream::CAudioStream (CAudioContext& context, const std::string& filename)
|
|||||||
this->loadCustomContent (filename.c_str ());
|
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) {
|
m_audioContext (context) {
|
||||||
// setup a custom context first
|
// setup a custom context first
|
||||||
this->m_formatContext = avformat_alloc_context ();
|
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_buffer = buffer;
|
||||||
this->m_length = length;
|
this->m_length = length;
|
||||||
this->m_position = 0;
|
|
||||||
|
|
||||||
// setup custom io for it
|
// setup custom io for it
|
||||||
this->m_formatContext->pb = avio_alloc_context (static_cast<uint8_t*> (av_malloc (4096)), 4096, 0, this,
|
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;
|
return this->m_repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const uint8_t[]> CAudioStream::getBuffer () {
|
ReadStreamSharedPtr& CAudioStream::getBuffer () {
|
||||||
return this->m_buffer;
|
return this->m_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,14 +335,6 @@ uint32_t CAudioStream::getLength () const {
|
|||||||
return this->m_length;
|
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 () {
|
SDL_cond* CAudioStream::getWaitCondition () {
|
||||||
return this->m_queue->wait;
|
return this->m_queue->wait;
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,15 @@ extern "C" {
|
|||||||
namespace WallpaperEngine::Audio {
|
namespace WallpaperEngine::Audio {
|
||||||
class CAudioContext;
|
class CAudioContext;
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::FileSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a playable audio stream for the audio driver
|
* Represents a playable audio stream for the audio driver
|
||||||
*/
|
*/
|
||||||
class CAudioStream {
|
class CAudioStream {
|
||||||
public:
|
public:
|
||||||
CAudioStream (CAudioContext& context, const std::string& filename);
|
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 (CAudioContext& audioContext, AVCodecContext* context);
|
||||||
~CAudioStream ();
|
~CAudioStream ();
|
||||||
|
|
||||||
@ -88,21 +90,11 @@ class CAudioStream {
|
|||||||
/**
|
/**
|
||||||
* @return The file data buffer
|
* @return The file data buffer
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] std::shared_ptr<const uint8_t[]> getBuffer ();
|
[[nodiscard]] ReadStreamSharedPtr& getBuffer ();
|
||||||
/**
|
/**
|
||||||
* @return The length of the file data buffer
|
* @return The length of the file data buffer
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] uint32_t getLength () const;
|
[[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
|
* @return The SDL_cond used to signal waiting for data
|
||||||
*/
|
*/
|
||||||
@ -185,11 +177,9 @@ class CAudioStream {
|
|||||||
/** The stream index for the audio being played */
|
/** The stream index for the audio being played */
|
||||||
int m_audioStream = NO_AUDIO_STREAM;
|
int m_audioStream = NO_AUDIO_STREAM;
|
||||||
/** File data pointer */
|
/** File data pointer */
|
||||||
std::shared_ptr<const uint8_t[]> m_buffer = nullptr;
|
ReadStreamSharedPtr m_buffer = nullptr;
|
||||||
/** The length of the file data pointer */
|
/** The length of the file data pointer */
|
||||||
uint32_t m_length = 0;
|
uint32_t m_length = 0;
|
||||||
/** The read position on the file data pointer */
|
|
||||||
uint32_t m_position = 0;
|
|
||||||
|
|
||||||
struct MyAVPacketList {
|
struct MyAVPacketList {
|
||||||
AVPacket* packet;
|
AVPacket* packet;
|
||||||
|
23
src/WallpaperEngine/Data/Assets/Package.h
Normal file
23
src/WallpaperEngine/Data/Assets/Package.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
@ -7,9 +7,14 @@ namespace WallpaperEngine::Data::Assets {
|
|||||||
struct Mipmap;
|
struct Mipmap;
|
||||||
struct Frame;
|
struct Frame;
|
||||||
struct Texture;
|
struct Texture;
|
||||||
|
struct Package;
|
||||||
|
struct FileEntry;
|
||||||
|
|
||||||
using MipmapSharedPtr = std::shared_ptr <Mipmap>;
|
using MipmapSharedPtr = std::shared_ptr <Mipmap>;
|
||||||
using FrameSharedPtr = std::shared_ptr <Frame>;
|
using FrameSharedPtr = std::shared_ptr <Frame>;
|
||||||
using TextureUniquePtr = std::unique_ptr <Texture>;
|
using TextureUniquePtr = std::unique_ptr <Texture>;
|
||||||
|
using FileEntryUniquePtr = std::unique_ptr <FileEntry>;
|
||||||
|
using PackageUniquePtr = std::unique_ptr <Package>;
|
||||||
using MipmapList = std::vector <MipmapSharedPtr>;
|
using MipmapList = std::vector <MipmapSharedPtr>;
|
||||||
|
using FileEntryList = std::vector <FileEntryUniquePtr>;
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
namespace WallpaperEngine::Data::Model {
|
namespace WallpaperEngine::Data::Model {
|
||||||
/**
|
/**
|
||||||
@ -27,7 +28,6 @@ struct Project {
|
|||||||
bool supportsAudioProcessing;
|
bool supportsAudioProcessing;
|
||||||
/** All the available properties that the project defines for the user to change */
|
/** All the available properties that the project defines for the user to change */
|
||||||
Properties properties;
|
Properties properties;
|
||||||
|
|
||||||
/** The wallpaper this project defines */
|
/** The wallpaper this project defines */
|
||||||
WallpaperUniquePtr wallpaper;
|
WallpaperUniquePtr wallpaper;
|
||||||
/** VFS to access the project's files */
|
/** VFS to access the project's files */
|
||||||
|
@ -3,16 +3,12 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "WallpaperEngine/Assets/CContainer.h"
|
namespace WallpaperEngine::FileSystem {
|
||||||
|
class Container;
|
||||||
namespace WallpaperEngine::Assets {
|
|
||||||
class CContainer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace WallpaperEngine::Data::Model {
|
namespace WallpaperEngine::Data::Model {
|
||||||
struct Project;
|
struct Project;
|
||||||
class Wallpaper;
|
class Wallpaper;
|
||||||
@ -40,9 +36,6 @@ struct Effect;
|
|||||||
struct EffectPass;
|
struct EffectPass;
|
||||||
struct ModelStruct;
|
struct ModelStruct;
|
||||||
|
|
||||||
// TODO: REMOVE ONCE THESE ARE RENAMED AND MOVED
|
|
||||||
using Container = WallpaperEngine::Assets::CContainer;
|
|
||||||
|
|
||||||
using PropertySharedPtr = std::shared_ptr <Property>;
|
using PropertySharedPtr = std::shared_ptr <Property>;
|
||||||
using Properties = std::map <std::string, PropertySharedPtr>;
|
using Properties = std::map <std::string, PropertySharedPtr>;
|
||||||
using DynamicValueUniquePtr = std::unique_ptr <DynamicValue>;
|
using DynamicValueUniquePtr = std::unique_ptr <DynamicValue>;
|
||||||
@ -53,7 +46,7 @@ using ShaderConstantMap = std::map <std::string, UserSettingUniquePtr>;
|
|||||||
|
|
||||||
using ProjectUniquePtr = std::unique_ptr <Project>;
|
using ProjectUniquePtr = std::unique_ptr <Project>;
|
||||||
using WallpaperUniquePtr = std::unique_ptr <Wallpaper>;
|
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 SceneUniquePtr = std::unique_ptr <Scene>;
|
||||||
using WebUniquePtr = std::unique_ptr <Web>;
|
using WebUniquePtr = std::unique_ptr <Web>;
|
||||||
using VideoUniquePtr = std::unique_ptr <Video>;
|
using VideoUniquePtr = std::unique_ptr <Video>;
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
#include "EffectParser.h"
|
#include "EffectParser.h"
|
||||||
#include "MaterialParser.h"
|
#include "MaterialParser.h"
|
||||||
|
|
||||||
#include "WallpaperEngine/Data/Model/Material.h"
|
|
||||||
#include "WallpaperEngine/Data/Model/Effect.h"
|
#include "WallpaperEngine/Data/Model/Effect.h"
|
||||||
|
#include "WallpaperEngine/Data/Model/Material.h"
|
||||||
#include "WallpaperEngine/Data/Model/Project.h"
|
#include "WallpaperEngine/Data/Model/Project.h"
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Data::Parsers;
|
using namespace WallpaperEngine::Data::Parsers;
|
||||||
using namespace WallpaperEngine::Data::Model;
|
using namespace WallpaperEngine::Data::Model;
|
||||||
|
|
||||||
EffectUniquePtr EffectParser::load (Project& project, const std::string& filename) {
|
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);
|
return parse (effectJson, project);
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
#include "WallpaperEngine/Data/Model/Material.h"
|
#include "WallpaperEngine/Data/Model/Material.h"
|
||||||
#include "WallpaperEngine/Data/Model/Project.h"
|
#include "WallpaperEngine/Data/Model/Project.h"
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Data::Parsers;
|
using namespace WallpaperEngine::Data::Parsers;
|
||||||
using namespace WallpaperEngine::Data::Model;
|
using namespace WallpaperEngine::Data::Model;
|
||||||
|
|
||||||
MaterialUniquePtr MaterialParser::load (Project& project, const std::string& filename) {
|
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);
|
return parse (materialJson, project, filename);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
#include "ModelParser.h"
|
#include "ModelParser.h"
|
||||||
#include "MaterialParser.h"
|
#include "MaterialParser.h"
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Data/Model/Material.h"
|
||||||
#include "WallpaperEngine/Data/Model/Model.h"
|
#include "WallpaperEngine/Data/Model/Model.h"
|
||||||
#include "WallpaperEngine/Data/Model/Project.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::Parsers;
|
||||||
using namespace WallpaperEngine::Data::Model;
|
using namespace WallpaperEngine::Data::Model;
|
||||||
|
|
||||||
ModelUniquePtr ModelParser::load (Project& project, const std::string& filename) {
|
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);
|
return parse (model, project, filename);
|
||||||
}
|
}
|
||||||
|
48
src/WallpaperEngine/Data/Parsers/PackageParser.cpp
Normal file
48
src/WallpaperEngine/Data/Parsers/PackageParser.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
17
src/WallpaperEngine/Data/Parsers/PackageParser.h
Normal file
17
src/WallpaperEngine/Data/Parsers/PackageParser.h
Normal 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);
|
||||||
|
};
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "PropertyParser.h"
|
#include "PropertyParser.h"
|
||||||
#include "WallpaperEngine/Data/Model/Wallpaper.h"
|
#include "WallpaperEngine/Data/Model/Wallpaper.h"
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Data::Parsers;
|
using namespace WallpaperEngine::Data::Parsers;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ TextureUniquePtr TextureParser::parse (BinaryReader& file) {
|
|||||||
result->height = file.nextUInt32 ();
|
result->height = file.nextUInt32 ();
|
||||||
|
|
||||||
// ignore some more bytes
|
// ignore some more bytes
|
||||||
file.nextUInt32 ();
|
std::ignore = file.nextUInt32 ();
|
||||||
|
|
||||||
file.next (magic, 9);
|
file.next (magic, 9);
|
||||||
|
|
||||||
@ -114,13 +114,13 @@ MipmapSharedPtr TextureParser::parseMipmap (BinaryReader& file, Texture& header)
|
|||||||
if (header.containerVersion == ContainerVersion_TEXB0004) {
|
if (header.containerVersion == ContainerVersion_TEXB0004) {
|
||||||
// some integers that we can ignore as they only seem to affect
|
// some integers that we can ignore as they only seem to affect
|
||||||
// the editor
|
// the editor
|
||||||
file.nextUInt32 ();
|
std::ignore = file.nextUInt32 ();
|
||||||
file.nextUInt32 ();
|
std::ignore = file.nextUInt32 ();
|
||||||
// this format includes some json in the header that we might need
|
// this format includes some json in the header that we might need
|
||||||
// to parse at some point...
|
// to parse at some point...
|
||||||
result->json = file.nextNullTerminatedString ();
|
result->json = file.nextNullTerminatedString ();
|
||||||
// last ignorable integer
|
// last ignorable integer
|
||||||
file.nextUInt32 ();
|
std::ignore = file.nextUInt32 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
result->width = file.nextUInt32 ();
|
result->width = file.nextUInt32 ();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "ObjectParser.h"
|
#include "ObjectParser.h"
|
||||||
#include "WallpaperEngine/Data/Model/Project.h"
|
#include "WallpaperEngine/Data/Model/Project.h"
|
||||||
#include "WallpaperEngine/Data/Model/Wallpaper.h"
|
#include "WallpaperEngine/Data/Model/Wallpaper.h"
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
#include "WallpaperEngine/Logging/CLog.h"
|
#include "WallpaperEngine/Logging/CLog.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Data::Parsers;
|
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) {
|
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 camera = scene.require ("camera", "Scenes must have a camera section");
|
||||||
const auto general = scene.require ("general", "Scenes must have a general 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");
|
const auto projection = general.require ("orthogonalprojection", "General section must have orthogonal projection info");
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
using namespace WallpaperEngine::Data::Utils;
|
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];
|
char buffer[4];
|
||||||
|
|
||||||
this->m_input.read (buffer, 4);
|
this->m_input->read (buffer, 4);
|
||||||
|
|
||||||
if constexpr (std::endian::native == std::endian::little) {
|
if constexpr (std::endian::native == std::endian::little) {
|
||||||
return (buffer [3] & 0xFF) << 24 |
|
return (buffer [3] & 0xFF) << 24 |
|
||||||
@ -27,10 +27,10 @@ uint32_t BinaryReader::nextUInt32 () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int BinaryReader::nextInt () {
|
int BinaryReader::nextInt () const {
|
||||||
char buffer[4];
|
char buffer[4];
|
||||||
|
|
||||||
this->m_input.read (buffer, 4);
|
this->m_input->read (buffer, 4);
|
||||||
|
|
||||||
if constexpr (std::endian::native == std::endian::little) {
|
if constexpr (std::endian::native == std::endian::little) {
|
||||||
return (buffer [3] & 0xFF) << 24 |
|
return (buffer [3] & 0xFF) << 24 |
|
||||||
@ -45,17 +45,17 @@ int BinaryReader::nextInt () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float BinaryReader::nextFloat () {
|
float BinaryReader::nextFloat () const {
|
||||||
float result;
|
float result;
|
||||||
static_assert (std::endian::native == std::endian::little, "Only little endian is supported for floats");
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string BinaryReader::nextNullTerminatedString () {
|
std::string BinaryReader::nextNullTerminatedString () const {
|
||||||
std::string output;
|
std::string output;
|
||||||
|
|
||||||
while (const auto c = this->next ()) {
|
while (const auto c = this->next ()) {
|
||||||
@ -65,13 +65,26 @@ std::string BinaryReader::nextNullTerminatedString () {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinaryReader::next (char* out, size_t size) {
|
std::string BinaryReader::nextSizedString () const {
|
||||||
this->m_input.read (out, size);
|
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;
|
char buffer;
|
||||||
this->m_input.read (&buffer, 1);
|
this->m_input->read (&buffer, 1);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::istream& BinaryReader::base () const {
|
||||||
|
return *this->m_input;
|
||||||
|
}
|
||||||
|
@ -2,20 +2,29 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace WallpaperEngine::Data::Utils {
|
namespace WallpaperEngine::Data::Utils {
|
||||||
|
using ReadStream = std::istream;
|
||||||
|
using ReadStreamSharedPtr = std::shared_ptr<ReadStream>;
|
||||||
|
|
||||||
class BinaryReader {
|
class BinaryReader {
|
||||||
public:
|
public:
|
||||||
explicit BinaryReader (std::istream& file);
|
explicit BinaryReader (ReadStreamSharedPtr file);
|
||||||
|
|
||||||
uint32_t nextUInt32 ();
|
[[nodiscard]] uint32_t nextUInt32 () const;
|
||||||
int nextInt ();
|
[[nodiscard]] int nextInt () const;
|
||||||
float nextFloat ();
|
[[nodiscard]] float nextFloat () const;
|
||||||
std::string nextNullTerminatedString ();
|
[[nodiscard]] std::string nextNullTerminatedString () const;
|
||||||
void next(char* out, size_t size);
|
[[nodiscard]] std::string nextSizedString () const;
|
||||||
char next ();
|
void next(char* out, size_t size) const;
|
||||||
|
[[nodiscard]] char next () const;
|
||||||
|
|
||||||
|
[[nodiscard]] std::istream& base () const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::istream& m_input;
|
ReadStreamSharedPtr m_input;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using BinaryReaderUniquePtr = std::unique_ptr<BinaryReader>;
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,21 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace WallpaperEngine::Data::Utils {
|
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>;
|
||||||
}
|
}
|
87
src/WallpaperEngine/FileSystem/Adapters/Directory.cpp
Normal file
87
src/WallpaperEngine/FileSystem/Adapters/Directory.cpp
Normal 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);
|
||||||
|
}
|
25
src/WallpaperEngine/FileSystem/Adapters/Directory.h
Normal file
25
src/WallpaperEngine/FileSystem/Adapters/Directory.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
64
src/WallpaperEngine/FileSystem/Adapters/Package.cpp
Normal file
64
src/WallpaperEngine/FileSystem/Adapters/Package.cpp
Normal 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));
|
||||||
|
}
|
||||||
|
|
29
src/WallpaperEngine/FileSystem/Adapters/Package.h
Normal file
29
src/WallpaperEngine/FileSystem/Adapters/Package.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
28
src/WallpaperEngine/FileSystem/Adapters/Types.h
Normal file
28
src/WallpaperEngine/FileSystem/Adapters/Types.h
Normal 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
|
59
src/WallpaperEngine/FileSystem/Adapters/Virtual.cpp
Normal file
59
src/WallpaperEngine/FileSystem/Adapters/Virtual.cpp
Normal 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> ();
|
||||||
|
}
|
||||||
|
|
32
src/WallpaperEngine/FileSystem/Adapters/Virtual.h
Normal file
32
src/WallpaperEngine/FileSystem/Adapters/Virtual.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
126
src/WallpaperEngine/FileSystem/Container.cpp
Normal file
126
src/WallpaperEngine/FileSystem/Container.cpp
Normal 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);
|
||||||
|
}
|
70
src/WallpaperEngine/FileSystem/Container.h
Normal file
70
src/WallpaperEngine/FileSystem/Container.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
@ -15,7 +15,7 @@ Wallpapers::CScene& CObject::getScene () const {
|
|||||||
return this->m_scene;
|
return this->m_scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CContainer& CObject::getContainer () const {
|
const Container& CObject::getContainer () const {
|
||||||
return this->getScene ().getContainer ();
|
return this->getScene ().getContainer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class CObject : public Helpers::CContextAware {
|
|||||||
virtual void render () = 0;
|
virtual void render () = 0;
|
||||||
|
|
||||||
[[nodiscard]] Wallpapers::CScene& getScene () const;
|
[[nodiscard]] Wallpapers::CScene& getScene () const;
|
||||||
[[nodiscard]] const CContainer& getContainer () const;
|
[[nodiscard]] const Container& getContainer () const;
|
||||||
[[nodiscard]] int getId () const;
|
[[nodiscard]] int getId () const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
#include "CTextureCache.h"
|
#include "CTextureCache.h"
|
||||||
|
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
#include "WallpaperEngine/Assets/CAssetLoadException.h"
|
#include "WallpaperEngine/Assets/CAssetLoadException.h"
|
||||||
|
#include "WallpaperEngine/Assets/CTexture.h"
|
||||||
#include "WallpaperEngine/Render/Helpers/CContextAware.h"
|
#include "WallpaperEngine/Render/Helpers/CContextAware.h"
|
||||||
|
|
||||||
#include "WallpaperEngine/Data/Model/Project.h"
|
#include "WallpaperEngine/Data/Model/Project.h"
|
||||||
|
#include "WallpaperEngine/Data/Parsers/TextureParser.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Render;
|
using namespace WallpaperEngine::Render;
|
||||||
using namespace WallpaperEngine::Assets;
|
using namespace WallpaperEngine::FileSystem;
|
||||||
|
using namespace WallpaperEngine::Data::Parsers;
|
||||||
|
|
||||||
CTextureCache::CTextureCache (CRenderContext& context) : Helpers::CContextAware (context) {}
|
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 ())
|
if (found != this->m_textureCache.end ())
|
||||||
return found->second;
|
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
|
// search for the texture in all the different containers just in case
|
||||||
for (const auto& [name, project] : this->getContext ().getApp ().getBackgrounds ()) {
|
for (const auto& [name, project] : this->getContext ().getApp ().getBackgrounds ()) {
|
||||||
try {
|
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);
|
this->store (filename, texture);
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ CWallpaper::CWallpaper (
|
|||||||
|
|
||||||
CWallpaper::~CWallpaper () = default;
|
CWallpaper::~CWallpaper () = default;
|
||||||
|
|
||||||
const CContainer& CWallpaper::getContainer () const {
|
const Container& CWallpaper::getContainer () const {
|
||||||
return *this->m_wallpaperData.project.container;
|
return *this->m_wallpaperData.project.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#include "WallpaperEngine/Assets/CContainer.h"
|
|
||||||
#include "WallpaperEngine/Audio/CAudioContext.h"
|
#include "WallpaperEngine/Audio/CAudioContext.h"
|
||||||
|
|
||||||
#include "WallpaperEngine/Render/CFBO.h"
|
#include "WallpaperEngine/Render/CFBO.h"
|
||||||
@ -27,6 +26,7 @@ class CContextAware;
|
|||||||
using namespace WallpaperEngine::Assets;
|
using namespace WallpaperEngine::Assets;
|
||||||
using namespace WallpaperEngine::Audio;
|
using namespace WallpaperEngine::Audio;
|
||||||
using namespace WallpaperEngine::Data::Model;
|
using namespace WallpaperEngine::Data::Model;
|
||||||
|
using namespace WallpaperEngine::FileSystem;
|
||||||
|
|
||||||
class CWallpaper : public Helpers::CContextAware, public CFBOProvider {
|
class CWallpaper : public Helpers::CContextAware, public CFBOProvider {
|
||||||
public:
|
public:
|
||||||
@ -65,7 +65,7 @@ class CWallpaper : public Helpers::CContextAware, public CFBOProvider {
|
|||||||
/**
|
/**
|
||||||
* @return The container to resolve files for this wallpaper
|
* @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
|
* @return The current audio context for this wallpaper
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "CSound.h"
|
#include "CSound.h"
|
||||||
|
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Render::Objects;
|
using namespace WallpaperEngine::Render::Objects;
|
||||||
|
|
||||||
CSound::CSound (Wallpapers::CScene& scene, const Sound& sound) :
|
CSound::CSound (Wallpapers::CScene& scene, const Sound& sound) :
|
||||||
@ -16,21 +18,17 @@ CSound::~CSound() {
|
|||||||
for (const auto& stream : this->m_audioStreams) {
|
for (const auto& stream : this->m_audioStreams) {
|
||||||
delete stream;
|
delete stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_soundBuffer.clear ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSound::load () {
|
void CSound::load () {
|
||||||
for (const auto& cur : this->m_sound.sounds) {
|
for (const auto& cur : this->m_sound.sounds) {
|
||||||
uint32_t filesize = 0;
|
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);
|
auto stream = new Audio::CAudioStream (this->getScene ().getAudioContext (), filebuffer, filesize);
|
||||||
|
|
||||||
stream->setRepeat (this->m_sound.playbackmode.has_value() && this->m_sound.playbackmode == "loop");
|
stream->setRepeat (this->m_sound.playbackmode.has_value() && this->m_sound.playbackmode == "loop");
|
||||||
|
|
||||||
this->m_audioStreams.push_back (stream);
|
this->m_audioStreams.push_back (stream);
|
||||||
this->m_soundBuffer.push_back (filebuffer);
|
|
||||||
|
|
||||||
// add the stream to the context so it can be played
|
// add the stream to the context so it can be played
|
||||||
this->getScene ().getAudioContext ().addStream (stream);
|
this->getScene ().getAudioContext ().addStream (stream);
|
||||||
|
@ -23,7 +23,6 @@ class CSound final : public CObject {
|
|||||||
void load ();
|
void load ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::shared_ptr<const uint8_t[]>> m_soundBuffer = {};
|
|
||||||
std::vector<Audio::CAudioStream*> m_audioStreams = {};
|
std::vector<Audio::CAudioStream*> m_audioStreams = {};
|
||||||
|
|
||||||
const Sound& m_sound;
|
const Sound& m_sound;
|
||||||
|
@ -9,21 +9,64 @@
|
|||||||
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
|
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
|
||||||
|
|
||||||
#include "CGLSLContext.h"
|
#include "CGLSLContext.h"
|
||||||
|
#include "WallpaperEngine/Assets/CAssetLoadException.h"
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Assets;
|
using namespace WallpaperEngine::Assets;
|
||||||
|
|
||||||
namespace WallpaperEngine::Render::Shaders {
|
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 (
|
CShader::CShader (
|
||||||
const CContainer& container, std::string filename,
|
const Container& container, std::string filename,
|
||||||
const ComboMap& combos, const ComboMap& overrideCombos,
|
const ComboMap& combos, const ComboMap& overrideCombos,
|
||||||
const TextureMap& textures, const TextureMap& overrideTextures,
|
const TextureMap& textures, const TextureMap& overrideTextures,
|
||||||
const ShaderConstantMap& constants
|
const ShaderConstantMap& constants
|
||||||
) :
|
) :
|
||||||
m_vertex (
|
m_vertex (
|
||||||
CGLSLContext::UnitType_Vertex, filename, container.readVertexShader (filename),
|
CGLSLContext::UnitType_Vertex, filename, readVertex (filename, container),
|
||||||
container, constants, textures, overrideTextures, combos, overrideCombos),
|
container, constants, textures, overrideTextures, combos, overrideCombos),
|
||||||
m_fragment (
|
m_fragment (
|
||||||
CGLSLContext::UnitType_Fragment, filename, container.readFragmentShader (filename),
|
CGLSLContext::UnitType_Fragment, filename, readFragment (filename, container),
|
||||||
container, constants, textures, overrideTextures, combos, overrideCombos),
|
container, constants, textures, overrideTextures, combos, overrideCombos),
|
||||||
m_file (std::move (filename)),
|
m_file (std::move (filename)),
|
||||||
m_combos (combos),
|
m_combos (combos),
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "WallpaperEngine/Assets/CContainer.h"
|
|
||||||
#include "WallpaperEngine/Assets/ITexture.h"
|
#include "WallpaperEngine/Assets/ITexture.h"
|
||||||
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.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
|
* @param recursive Whether the compiler should add base definitions or not
|
||||||
*/
|
*/
|
||||||
CShader (
|
CShader (
|
||||||
const CContainer& container, std::string filename,
|
const Container& container, std::string filename,
|
||||||
const ComboMap& combos, const ComboMap& overrideCombos,
|
const ComboMap& combos, const ComboMap& overrideCombos,
|
||||||
const TextureMap& textures, const TextureMap& overrideTextures,
|
const TextureMap& textures, const TextureMap& overrideTextures,
|
||||||
const ShaderConstantMap& constants);
|
const ShaderConstantMap& constants);
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.h"
|
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.h"
|
||||||
|
|
||||||
#include "WallpaperEngine/Data/Builders/VectorBuilder.h"
|
#include "WallpaperEngine/Data/Builders/VectorBuilder.h"
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
#define SHADER_HEADER(filename) "#version 330\n" \
|
#define SHADER_HEADER(filename) "#version 330\n" \
|
||||||
"// ======================================================\n" \
|
"// ======================================================\n" \
|
||||||
@ -52,7 +53,7 @@ using namespace WallpaperEngine::Data::Builders;
|
|||||||
using namespace WallpaperEngine::Render::Shaders;
|
using namespace WallpaperEngine::Render::Shaders;
|
||||||
|
|
||||||
CShaderUnit::CShaderUnit (
|
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 ShaderConstantMap& constants, const TextureMap& passTextures, const TextureMap& overrideTextures,
|
||||||
const ComboMap& combos, const ComboMap& overrideCombos
|
const ComboMap& combos, const ComboMap& overrideCombos
|
||||||
) :
|
) :
|
||||||
@ -151,7 +152,8 @@ void CShaderUnit::preprocessIncludes () {
|
|||||||
content += "// begin of include from file ";
|
content += "// begin of include from file ";
|
||||||
content += filename;
|
content += filename;
|
||||||
content += "\n";
|
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 += "\n// end of included from file ";
|
||||||
content += filename;
|
content += filename;
|
||||||
content += "\n";
|
content += "\n";
|
||||||
@ -190,7 +192,8 @@ void CShaderUnit::preprocessIncludes () {
|
|||||||
content = "// begin of include from file ";
|
content = "// begin of include from file ";
|
||||||
content += filename;
|
content += filename;
|
||||||
content += "\n";
|
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 += "\n// end of included from file ";
|
||||||
content += filename;
|
content += filename;
|
||||||
content += "\n";
|
content += "\n";
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "CGLSLContext.h"
|
#include "CGLSLContext.h"
|
||||||
#include "WallpaperEngine/Assets/CContainer.h"
|
|
||||||
#include "WallpaperEngine/Data/JSON.h"
|
#include "WallpaperEngine/Data/JSON.h"
|
||||||
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
|
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
|
||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
@ -14,7 +13,7 @@
|
|||||||
|
|
||||||
namespace WallpaperEngine::Render::Shaders {
|
namespace WallpaperEngine::Render::Shaders {
|
||||||
using JSON = WallpaperEngine::Data::JSON::JSON;
|
using JSON = WallpaperEngine::Data::JSON::JSON;
|
||||||
using namespace WallpaperEngine::Assets;
|
using namespace WallpaperEngine::FileSystem;
|
||||||
using namespace WallpaperEngine::Data::Model;
|
using namespace WallpaperEngine::Data::Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,7 +22,7 @@ using namespace WallpaperEngine::Data::Model;
|
|||||||
class CShaderUnit {
|
class CShaderUnit {
|
||||||
public:
|
public:
|
||||||
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 ShaderConstantMap& constants, const TextureMap& passTextures,
|
||||||
const TextureMap& overrideTextures, const ComboMap& combos, const ComboMap& overrideCombos);
|
const TextureMap& overrideTextures, const ComboMap& combos, const ComboMap& overrideCombos);
|
||||||
~CShaderUnit () = default;
|
~CShaderUnit () = default;
|
||||||
@ -159,6 +158,6 @@ class CShaderUnit {
|
|||||||
/**
|
/**
|
||||||
* The container to source files from
|
* The container to source files from
|
||||||
*/
|
*/
|
||||||
const CContainer& m_container;
|
const Container& m_container;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ CVideo::CVideo (
|
|||||||
sLog.exception ("Failed to initialize MPV's GL context");
|
sLog.exception ("Failed to initialize MPV's GL context");
|
||||||
|
|
||||||
const std::filesystem::path videopath =
|
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
|
// build the path to the video file
|
||||||
const char* command [] = {"loadfile", videopath.c_str (), nullptr};
|
const char* command [] = {"loadfile", videopath.c_str (), nullptr};
|
||||||
|
@ -48,7 +48,7 @@ bool CWPSchemeHandler::Open(CefRefPtr<CefRequest> request,
|
|||||||
this->m_mimeType = mime;
|
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 ();
|
callback->Continue ();
|
||||||
} catch (CAssetLoadException&) {
|
} catch (CAssetLoadException&) {
|
||||||
#if !NDEBUG
|
#if !NDEBUG
|
||||||
@ -77,7 +77,8 @@ void CWPSchemeHandler::GetResponseHeaders(CefRefPtr<CefResponse> response,
|
|||||||
response->SetMimeType (this->m_mimeType);
|
response->SetMimeType (this->m_mimeType);
|
||||||
response->SetStatus (200);
|
response->SetStatus (200);
|
||||||
|
|
||||||
response_length = this->m_filesize;
|
// signals an unknown-length file
|
||||||
|
response_length = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWPSchemeHandler::Cancel () {
|
void CWPSchemeHandler::Cancel () {
|
||||||
@ -90,14 +91,18 @@ bool CWPSchemeHandler::Read(void* data_out, int bytes_to_read, int& bytes_read,
|
|||||||
|
|
||||||
bytes_read = 0;
|
bytes_read = 0;
|
||||||
|
|
||||||
if (this->m_contents && this->m_offset < this->m_filesize) {
|
if (this->m_contents->eof ()) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
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;
|
||||||
|
}
|
@ -2,19 +2,18 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "WallpaperEngine/FileSystem/Container.h"
|
||||||
|
|
||||||
#include "include/cef_resource_handler.h"
|
#include "include/cef_resource_handler.h"
|
||||||
#include "include/wrapper/cef_helpers.h"
|
#include "include/wrapper/cef_helpers.h"
|
||||||
|
|
||||||
namespace WallpaperEngine::Assets {
|
|
||||||
class CContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace WallpaperEngine::Data::Model {
|
namespace WallpaperEngine::Data::Model {
|
||||||
class Project;
|
struct Project;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace WallpaperEngine::WebBrowser::CEF {
|
namespace WallpaperEngine::WebBrowser::CEF {
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::FileSystem;
|
||||||
using namespace WallpaperEngine::Data::Model;
|
using namespace WallpaperEngine::Data::Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,11 +39,9 @@ class CWPSchemeHandler : public CefResourceHandler {
|
|||||||
private:
|
private:
|
||||||
const Project& m_project;
|
const Project& m_project;
|
||||||
|
|
||||||
const Assets::CContainer& m_container;
|
const Container& m_container;
|
||||||
std::shared_ptr<const uint8_t[]> m_contents = nullptr;
|
ReadStreamSharedPtr m_contents = nullptr;
|
||||||
uint32_t m_filesize = 0;
|
std::string m_mimeType;
|
||||||
std::string m_mimeType = "";
|
|
||||||
uint32_t m_offset = 0;
|
|
||||||
|
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(CWPSchemeHandler);
|
IMPLEMENT_REFCOUNTING(CWPSchemeHandler);
|
||||||
|
Loading…
Reference in New Issue
Block a user