feat: added material command copy support

This commit is contained in:
Almamu 2025-04-22 00:41:48 +02:00
parent d648964ae2
commit 58f6a5c2e5
8 changed files with 139 additions and 46 deletions

View File

@ -187,6 +187,25 @@ void CWallpaperApplication::setupContainer (CCombinedContainer& container, const
)}}
);
virtualContainer->add(
"shaders/commands/copy.frag",
"uniform sampler2D g_Texture0;\n"
"in vec2 v_TexCoord;\n"
"void main () {\n"
"out_FragColor = texture (g_Texture0, v_TexCoord);\n"
"}"
);
virtualContainer->add(
"shaders/commands/copy.vert",
"in vec3 a_Position;\n"
"in vec2 a_TexCoord;\n"
"out vec2 v_TexCoord;\n"
"void main () {\n"
"gl_Position = vec4 (a_Position, 1.0);\n"
"v_TexCoord = a_TexCoord;\n"
"}"
);
container.add (virtualContainer);
}

View File

@ -19,6 +19,10 @@ void CVirtualContainer::add (const std::filesystem::path& filename, const std::s
this->add (filename, copy, contents.length () + 1);
}
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 ());
}

View File

@ -31,6 +31,14 @@ class CVirtualContainer final : public CContainer {
* @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

View File

@ -187,33 +187,45 @@ std::vector<const Images::CMaterial*> CEffect::materialsFromJSON (
for (const auto& cur : (*passes_it)) {
++materialNumber;
const auto materialfile = cur.find ("material");
const auto target = cur.find ("target");
const auto target_it = cur.find ("target");
const auto bind_it = cur.find ("bind");
if (materialfile == cur.end ())
sLog.exception ("Found an effect ", name, " without material");
std::map<int, const Effects::CBind*> textureBindings;
if (bind_it != cur.end ()) {
for (const auto& bindCur : (*bind_it)) {
const auto* bind = Effects::CBind::fromJSON (bindCur);
textureBindings.insert (std::pair (bind->getIndex (), bind));
}
}
const auto command_it = cur.find ("command");
const auto compose_it = cur.find ("compose");
const Images::CMaterial* material;
const Images::CMaterial::OverrideInfo* overrideInfo;
const auto overrideIt = overrides.find (materialNumber);
if (overrideIt != overrides.end ()) {
overrideInfo = &overrideIt->second;
if (compose_it != cur.end ()) {
sLog.error ("Composing materials is not supported yet...");
}
if (target == cur.end ())
material = Images::CMaterial::fromFile (materialfile->get<std::string> (), container, textureBindings, overrideInfo);
else
material = Images::CMaterial::fromFile (materialfile->get<std::string> (), *target, container, textureBindings, overrideInfo);
if (materialfile != cur.end ()) {
std::map<int, const Effects::CBind*> textureBindings;
if (bind_it != cur.end ()) {
for (const auto& bindCur : (*bind_it)) {
const auto* bind = Effects::CBind::fromJSON (bindCur);
textureBindings.insert (std::pair (bind->getIndex (), bind));
}
}
const Images::CMaterial::OverrideInfo* overrideInfo;
const auto overrideIt = overrides.find (materialNumber);
if (overrideIt != overrides.end ()) {
overrideInfo = &overrideIt->second;
}
if (target_it == cur.end ()) {
material = Images::CMaterial::fromFile (
materialfile->get<std::string> (), container, false, textureBindings, overrideInfo);
} else {
material = Images::CMaterial::fromFile (
materialfile->get<std::string> (), *target_it, container, false, textureBindings, overrideInfo);
}
} else if (command_it != cur.end ()) {
material = Images::CMaterial::fromCommand (cur);
} else {
sLog.exception ("Material without command nor material file: ", name, " (", materialNumber,")");
}
materials.push_back (material);
}

View File

@ -44,7 +44,8 @@ const WallpaperEngine::Core::CObject* CImage::fromJSON (
const auto material = Images::CMaterial::fromFile (
jsonFindRequired<std::string> (content, "material", "Image must have a material"),
container
container,
jsonFindDefault (content, "solidlayer", false)
);
if (effects_it != data.end () && effects_it->is_array ()) {

View File

@ -1,6 +1,7 @@
#include "CMaterial.h"
#include "WallpaperEngine/Core/Objects/Images/Materials/CPass.h"
#include "WallpaperEngine/Logging/CLog.h"
#include <nlohmann/json.hpp>
#include <utility>
@ -10,37 +11,39 @@ using namespace WallpaperEngine::Core::Objects;
using namespace WallpaperEngine::Core::Objects::Images;
CMaterial::CMaterial (
std::string name, std::map<int, const Effects::CBind*> textureBindings,
std::string name, bool solidlayer, std::map<int, const Effects::CBind*> textureBindings,
std::vector<const Materials::CPass*> passes
) :
m_name (std::move(name)),
m_textureBindings (std::move(textureBindings)),
m_passes (std::move(passes)) {}
m_passes (std::move(passes)),
m_solidlayer (solidlayer) {}
CMaterial::CMaterial (
std::string name, std::string target,
std::string name, std::string target, bool solidlayer,
std::map<int, const Effects::CBind*> textureBindings, std::vector<const Materials::CPass*> passes
) :
m_name (std::move(name)),
m_target (std::move(target)),
m_textureBindings (std::move(textureBindings)),
m_passes (std::move(passes)) {}
m_passes (std::move(passes)),
m_solidlayer (solidlayer) {}
const CMaterial* CMaterial::fromFile (
const std::filesystem::path& filename, const CContainer* container,
const std::filesystem::path& filename, const CContainer* container, bool solidlayer,
std::map<int, const Effects::CBind*> textureBindings, const OverrideInfo* overrides
) {
return fromJSON (filename, json::parse (container->readFileAsString (filename)), std::move(textureBindings), overrides);
return fromJSON (filename, json::parse (container->readFileAsString (filename)), solidlayer, std::move(textureBindings), overrides);
}
const CMaterial* CMaterial::fromFile (
const std::filesystem::path& filename, const std::string& target,
const CContainer* container, std::map<int, const Effects::CBind*> textureBindings, const OverrideInfo* overrides
const std::filesystem::path& filename, const std::string& target, const CContainer* container, bool solidlayer,
std::map<int, const Effects::CBind*> textureBindings, const OverrideInfo* overrides
) {
return fromJSON (filename, json::parse (container->readFileAsString (filename)), target, std::move(textureBindings), overrides);
return fromJSON (filename, json::parse (container->readFileAsString (filename)), target, solidlayer, std::move(textureBindings), overrides);
}
const CMaterial* CMaterial::fromJSON (
const std::string& name, const json& data, const std::string& target,
const std::string& name, const json& data, const std::string& target, bool solidlayer,
std::map<int, const Effects::CBind*> textureBindings, const OverrideInfo* overrides
) {
const auto passes_it = jsonFindRequired (data, "passes", "Material must have at least one pass");
@ -49,11 +52,11 @@ const CMaterial* CMaterial::fromJSON (
for (const auto& cur : (*passes_it))
passes.push_back (Materials::CPass::fromJSON (cur, overrides));
return new CMaterial (name, target, std::move(textureBindings), passes);
return new CMaterial (name, target, solidlayer, std::move(textureBindings), passes);
}
const CMaterial* CMaterial::fromJSON (
const std::string& name, const json& data, std::map<int, const Effects::CBind*> textureBindings,
const std::string& name, const json& data, bool solidlayer, std::map<int, const Effects::CBind*> textureBindings,
const OverrideInfo* overrides
) {
const auto passes_it = jsonFindRequired (data, "passes", "Material must have at least one pass");
@ -62,7 +65,34 @@ const CMaterial* CMaterial::fromJSON (
for (const auto& cur : (*passes_it))
passes.push_back (Materials::CPass::fromJSON (cur, overrides));
return new CMaterial (name, std::move(textureBindings), passes);
return new CMaterial (name, solidlayer, std::move(textureBindings), passes);
}
const CMaterial* CMaterial::fromCommand (const json& data) {
const std::string& command = jsonFindRequired <std::string> (data, "command", "Command material must have a command");
const std::string& target = jsonFindRequired <std::string> (data, "target", "Command material must have a target");
const std::string& source = jsonFindRequired <std::string> (data, "source", "Command material must have a source");
std::vector<const Materials::CPass*> passes;
if (command == "copy") {
passes.push_back (
Materials::CPass::fromJSON ({
{"blending", "normal"},
{"cullmode", "nocull"},
{"depthtest", "disabled"},
{"depthwrite", "disabled"},
{"shader", "commands/copy"},
{"textures", json::array ({source, target})}
}, nullptr)
);
} else if (command == "swap") {
// TODO: HOW TO IMPLEMENT THIS ONE?
sLog.exception ("Command material swap not implemented yet");
} else {
sLog.exception ("Unknown command: ", command);
}
return new CMaterial (command, false, {}, passes);
}
const std::vector<const Materials::CPass*>& CMaterial::getPasses () const {
@ -83,4 +113,8 @@ const std::string& CMaterial::getName () const {
bool CMaterial::hasTarget () const {
return !this->m_target.empty ();
}
bool CMaterial::isSolidLayer () const {
return this->m_solidlayer;
}

View File

@ -26,18 +26,20 @@ class CMaterial {
};
static const CMaterial* fromFile (
const std::filesystem::path& filename, const Assets::CContainer* container,
const std::filesystem::path& filename, const Assets::CContainer* container, bool solidlayer = false,
std::map<int, const Effects::CBind*> textureBindings = {}, const OverrideInfo* overrides = nullptr);
static const CMaterial* fromFile (
const std::filesystem::path& filename, const std::string& target,
const Assets::CContainer* container, std::map<int, const Effects::CBind*> textureBindings = {},
const std::filesystem::path& filename, const std::string& target, const Assets::CContainer* container,
bool solidlayer = false, std::map<int, const Effects::CBind*> textureBindings = {},
const OverrideInfo* overrides = nullptr);
static const CMaterial* fromJSON (
const std::string& name, const json& data,
const std::string& name, const json& data, bool solidlayer = false,
std::map<int, const Effects::CBind*> textureBindings = {}, const OverrideInfo* overrides = nullptr);
static const CMaterial* fromJSON (
const std::string& name, const json& data, const std::string& target,
const std::string& name, const json& data, const std::string& target, bool solidlayer = false,
std::map<int, const Effects::CBind*> textureBindings = {}, const OverrideInfo* overrides = nullptr);
static const CMaterial* fromCommand (const json& data);
/**
* @return All the rendering passes that happen for this material
*/
@ -59,13 +61,17 @@ class CMaterial {
* @return The name of the material
*/
[[nodiscard]] const std::string& getName () const;
/**
* @return If this material is a solidlayer or not
*/
[[nodiscard]] bool isSolidLayer () const;
protected:
CMaterial (
std::string name, std::map<int, const Effects::CBind*> textureBindings,
std::string name, bool solidlayer, std::map<int, const Effects::CBind*> textureBindings,
std::vector<const Materials::CPass*> passes);
CMaterial (
std::string name, std::string target, std::map<int, const Effects::CBind*> textureBindings,
std::string name, std::string target, bool solidlayer, std::map<int, const Effects::CBind*> textureBindings,
std::vector<const Materials::CPass*> passes);
private:
@ -77,5 +83,7 @@ class CMaterial {
const std::string m_target;
/** The material's name */
const std::string m_name;
/** If this material is a solid layer or not */
const bool m_solidlayer;
};
} // namespace WallpaperEngine::Core::Objects::Images

View File

@ -88,10 +88,17 @@ CImage::CImage (Wallpapers::CScene* scene, const Core::Objects::CImage* image) :
this->m_texture = this->getContext ().resolveTexture (textureName);
}
} else {
if (this->m_image->getMaterial ()->isSolidLayer()) {
size.x = scene_width;
size.y = scene_height;
}
// if (this->m_image->isSolid ()) // layer receives cursor events: https://docs.wallpaperengine.io/en/scene/scenescript/reference/event/cursor.html
// same applies to effects
// TODO: create a dummy texture of correct size, fbo constructors should be enough, but this should be properly
// handled
this->m_texture = new CFBO ("", ITexture::TextureFormat::ARGB8888, ITexture::TextureFlags::NoFlags, 1, size.x,
size.y, size.x, size.y);
this->m_texture = new CFBO (
"", ITexture::TextureFormat::ARGB8888, ITexture::TextureFlags::NoFlags, 1, size.x,
size.y, size.x, size.y);
}
// register both FBOs into the scene
@ -258,7 +265,7 @@ void CImage::setup () {
overrides.combos.insert (std::pair ("BLENDMODE", this->m_image->getColorBlendMode ()));
const auto material =
Core::Objects::Images::CMaterial::fromFile ("materials/util/effectpassthrough.json", this->getContainer (), {}, &overrides);
Core::Objects::Images::CMaterial::fromFile ("materials/util/effectpassthrough.json", this->getContainer (), false, {}, &overrides);
// generate the main material used to render the image
this->m_colorBlendMaterial = new Effects::CMaterial (