diff --git a/CMakeLists.txt b/CMakeLists.txt index 5156496..a3934dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,9 +192,7 @@ if(X11_SUPPORT_FOUND) src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp src/WallpaperEngine/Render/Drivers/Output/CX11Output.h src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.cpp - src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h - src/WallpaperEngine/Render/Shaders/CShaderUnit.cpp - src/WallpaperEngine/Render/Shaders/CShaderUnit.h) + src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h) SET(X11_INCLUDES ${X11_INCLUDE_DIR} ${XRANDR_INCLUDE_DIR}) @@ -318,8 +316,10 @@ add_executable( src/WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.h src/WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.cpp - src/WallpaperEngine/Render/Shaders/CShader.h - src/WallpaperEngine/Render/Shaders/CShader.cpp + src/WallpaperEngine/Render/Shaders/CShader.h + src/WallpaperEngine/Render/Shaders/CShader.cpp + src/WallpaperEngine/Render/Shaders/CShaderUnit.cpp + src/WallpaperEngine/Render/Shaders/CShaderUnit.h src/WallpaperEngine/Render/Shaders/CGLSLContext.cpp src/WallpaperEngine/Render/Shaders/CGLSLContext.h @@ -451,12 +451,16 @@ add_executable( src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.cpp src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.cpp + src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector2.h + src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector2.cpp src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.h src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.cpp src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.cpp src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.cpp + src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h + src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.cpp src/WallpaperEngine/Core/Objects/Particles/CControlPoint.cpp src/WallpaperEngine/Core/Objects/Particles/CControlPoint.h diff --git a/src/WallpaperEngine/Application/CWallpaperApplication.cpp b/src/WallpaperEngine/Application/CWallpaperApplication.cpp index 22eb015..d37d91a 100644 --- a/src/WallpaperEngine/Application/CWallpaperApplication.cpp +++ b/src/WallpaperEngine/Application/CWallpaperApplication.cpp @@ -191,12 +191,12 @@ Core::CProject* CWallpaperApplication::loadBackground (const std::string& bg) { void CWallpaperApplication::setupPropertiesForProject (const Core::CProject* project) { // show properties if required - for (const auto cur : project->getProperties ()) { + for (const auto [key, cur] : project->getProperties ()) { // update the value of the property - auto override = this->m_context.settings.general.properties.find (cur->getName ()); + auto override = this->m_context.settings.general.properties.find (key); if (override != this->m_context.settings.general.properties.end ()) { - sLog.out ("Applying override value for ", cur->getName ()); + sLog.out ("Applying override value for ", key); cur->update (override->second); } diff --git a/src/WallpaperEngine/Core/CProject.cpp b/src/WallpaperEngine/Core/CProject.cpp index f53ec62..1c5b691 100644 --- a/src/WallpaperEngine/Core/CProject.cpp +++ b/src/WallpaperEngine/Core/CProject.cpp @@ -14,12 +14,16 @@ using namespace WallpaperEngine::Assets; static int backgroundId = -1; -CProject::CProject (std::string title, std::string type, std::string workshopid, const CContainer* container) : +CProject::CProject ( + std::string title, std::string type, std::string workshopid, const CContainer* container, + const std::map properties +) : m_workshopid(std::move(workshopid)), m_title (std::move(title)), m_type (std::move(type)), m_wallpaper (nullptr), - m_container (container) {} + m_container (container), + m_properties (properties) {} CProject* CProject::fromFile (const std::string& filename, const CContainer* container) { json content = json::parse (container->readFileAsString (filename)); @@ -36,14 +40,32 @@ CProject* CProject::fromFile (const std::string& filename, const CContainer* con const auto file = jsonFindRequired (content, "file", "Project's main file missing"); auto general = content.find ("general"); const CWallpaper* wallpaper; + std::map properties; std::transform (type.begin (), type.end (), type.begin (), tolower); + if (general != content.end ()) { + const auto properties_it = general->find ("properties"); + + if (properties_it != general->end ()) { + for (const auto& cur : properties_it->items ()) { + const auto property = Projects::CProperty::fromJSON (cur.value (), cur.key ()); + + if (property == nullptr) { + continue; + } + + properties.insert (std::pair (property->getName (), property)); + } + } + } + auto* project = new CProject ( jsonFindRequired (content, "title", "Project title missing"), type, jsonFindDefault (content, "workshopid", std::to_string (backgroundId--)), - container + container, + properties ); if (type == "scene") @@ -57,17 +79,6 @@ CProject* CProject::fromFile (const std::string& filename, const CContainer* con project->setWallpaper (wallpaper); - if (general != content.end ()) { - const auto properties = general->find ("properties"); - - if (properties != general->end ()) { - for (const auto& cur : properties->items ()) { - const auto property = Projects::CProperty::fromJSON (cur.value (), cur.key ()); - if (property != nullptr) - project->insertProperty (property); - } - } - } return project; } @@ -87,7 +98,7 @@ const std::string& CProject::getType () const { return this->m_type; } -const std::vector& CProject::getProperties () const { +const std::map& CProject::getProperties () const { return this->m_properties; } @@ -98,7 +109,3 @@ const std::string& CProject::getWorkshopId () const { const CContainer* CProject::getContainer () const { return this->m_container; } - -void CProject::insertProperty (const Projects::CProperty* property) { - this->m_properties.push_back (property); -} \ No newline at end of file diff --git a/src/WallpaperEngine/Core/CProject.h b/src/WallpaperEngine/Core/CProject.h index 5949a35..84fa4f5 100644 --- a/src/WallpaperEngine/Core/CProject.h +++ b/src/WallpaperEngine/Core/CProject.h @@ -20,19 +20,20 @@ class CProject { [[nodiscard]] const std::string& getTitle () const; [[nodiscard]] const std::string& getType () const; - [[nodiscard]] const std::vector& getProperties () const; + [[nodiscard]] const std::map& getProperties () const; [[nodiscard]] const std::string& getWorkshopId () const; const CContainer* getContainer () const; protected: - CProject (std::string title, std::string type, std::string workshopid, const CContainer* container); + CProject ( + std::string title, std::string type, std::string workshopid, const CContainer* container, + std::map properties); void setWallpaper (const CWallpaper* wallpaper); - void insertProperty (const Projects::CProperty* property); private: - std::vector m_properties; + std::map m_properties; const std::string m_workshopid; const std::string m_title; diff --git a/src/WallpaperEngine/Core/Objects/CEffect.cpp b/src/WallpaperEngine/Core/Objects/CEffect.cpp index e591ef5..62e1d7f 100644 --- a/src/WallpaperEngine/Core/Objects/CEffect.cpp +++ b/src/WallpaperEngine/Core/Objects/CEffect.cpp @@ -8,7 +8,10 @@ #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h" +#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector2.h" +#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h" +#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h" #include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h" #include "WallpaperEngine/Logging/CLog.h" @@ -53,7 +56,7 @@ const CEffect* CEffect::fromJSON ( fbos = CEffect::fbosFromJSON (fbos_it); if (effectpasses_it != data.end ()) { - overrides = overridesFromJSON (effectpasses_it, material); + overrides = overridesFromJSON (effectpasses_it, material, project); } return new CEffect ( @@ -83,39 +86,70 @@ std::map CEffect::combosFromJSON (const json::const_iterator& } std::map CEffect::constantsFromJSON ( - const json::const_iterator& constants_it + const json::const_iterator& constants_it, const CProject& project ) { std::map constants; for (auto& cur : constants_it->items ()) { auto val = cur.value (); - Effects::Constants::CShaderConstant* constant; + Effects::Constants::CShaderConstant* constant = nullptr; // if the constant is an object, that means the constant has some extra information // for the UI, take the value, which is what we need - // TODO: SUPPORT USER SETTINGS HERE if (cur.value ().is_object ()) { + auto user = cur.value ().find ("user"); auto it = cur.value ().find ("value"); - if (it == cur.value ().end ()) { - sLog.error ("Found object for shader constant without \"value\" member"); + if (user == cur.value ().end () && it == cur.value ().end ()) { + sLog.error (R"(Found object for shader constant without "value" and "user" setting)"); continue; } - val = it.value (); + if (user != cur.value ().end ()) { + // look for a property with the correct name + const auto& properties = project.getProperties (); + const auto property = properties.find (*user); + + if (property == properties.end ()) { + sLog.exception ("Shader constant pointing to non-existant project property: ", user->get ()); + } + + constant = new Effects::Constants::CShaderConstantProperty (property->second); + } else { + val = it.value (); + } } - if (val.is_number_float ()) { - constant = new Effects::Constants::CShaderConstantFloat (val.get ()); - } else if (val.is_number_integer ()) { - constant = new Effects::Constants::CShaderConstantInteger (val.get ()); - } else if (val.is_string ()) { - // try a vector 4 first, then a vector3 and then a vector 2 - constant = new Effects::Constants::CShaderConstantVector4 (WallpaperEngine::Core::aToVector4 (val)); - } else { - sLog.exception ("unknown shader constant type ", val); + // TODO: REFACTOR THIS SO IT'S NOT SO DEEP INTO THE FUNCTION + if (constant == nullptr) { + if (val.is_number_float ()) { + constant = new Effects::Constants::CShaderConstantFloat (val.get ()); + } else if (val.is_number_integer ()) { + constant = new Effects::Constants::CShaderConstantInteger (val.get ()); + } else if (val.is_string ()) { + // count the amount of spaces to determine which type of vector we have + std::string value = val; + + size_t spaces = + std::count_if (value.begin (), value.end (), [&] (const auto& item) { return item == ' '; }); + + if (spaces == 1) { + constant = + new Effects::Constants::CShaderConstantVector2 (WallpaperEngine::Core::aToVector2 (value)); + } else if (spaces == 2) { + constant = + new Effects::Constants::CShaderConstantVector3 (WallpaperEngine::Core::aToVector3 (value)); + } else if (spaces == 3) { + constant = + new Effects::Constants::CShaderConstantVector4 (WallpaperEngine::Core::aToVector4 (value)); + } else { + sLog.exception ("unknown shader constant type ", value); + } + } else { + sLog.exception ("unknown shader constant type ", val); + } } constants.insert (std::pair (cur.key (), constant)); @@ -187,7 +221,7 @@ std::vector CEffect::materialsFromJSON ( } std::map CEffect::overridesFromJSON ( - const json::const_iterator& passes_it, const Images::CMaterial* material + const json::const_iterator& passes_it, const Images::CMaterial* material, const CProject& project ) { std::map result; @@ -205,7 +239,7 @@ std::map CEffect::overridesFromJSON ( } if (constants_it != cur.end ()) { - override.constants = CEffect::constantsFromJSON (constants_it); + override.constants = CEffect::constantsFromJSON (constants_it, project); } if (textures_it != cur.end ()) { diff --git a/src/WallpaperEngine/Core/Objects/CEffect.h b/src/WallpaperEngine/Core/Objects/CEffect.h index 7f084c3..a50cda3 100644 --- a/src/WallpaperEngine/Core/Objects/CEffect.h +++ b/src/WallpaperEngine/Core/Objects/CEffect.h @@ -66,7 +66,7 @@ class CEffect { protected: static std::map constantsFromJSON ( - const json::const_iterator& constants_it); + const json::const_iterator& constants_it, const CProject& project); static std::map combosFromJSON (const json::const_iterator& combos_it); static std::vector fbosFromJSON (const json::const_iterator& fbos_it); static std::vector dependenciesFromJSON (const json::const_iterator& dependencies_it); @@ -74,7 +74,7 @@ class CEffect { const json::const_iterator& passes_it, const std::string& name, const CContainer* container, std::map); static std::map overridesFromJSON ( - const json::const_iterator& passes_it, const Images::CMaterial* material); + const json::const_iterator& passes_it, const Images::CMaterial* material, const CProject& project); private: /** Effect's name */ diff --git a/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h b/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h index dcf15f8..d2fcf79 100644 --- a/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h +++ b/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h @@ -11,17 +11,17 @@ class CShaderConstant { public: explicit CShaderConstant (std::string type); - template const T* as () const { + template [[nodiscard]] const T* as () const { assert (is ()); return reinterpret_cast (this); } - template T* as () { + template [[nodiscard]] T* as () { assert (is ()); return reinterpret_cast (this); } - template bool is () const { + template [[nodiscard]] bool is () const { return this->m_type == T::Type; } diff --git a/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.cpp b/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.cpp new file mode 100644 index 0000000..b2e3a31 --- /dev/null +++ b/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.cpp @@ -0,0 +1,17 @@ +#include "CShaderConstantProperty.h" + +using namespace WallpaperEngine::Core::Objects::Effects::Constants; + +CShaderConstantProperty::CShaderConstantProperty (const CProperty* property) : + CShaderConstant (Type), + m_property (property) {} + +const CProperty* CShaderConstantProperty::getProperty () const { + return this->m_property; +} + +std::string CShaderConstantProperty::toString () const { + return "no string representation yet!"; +} + +const std::string CShaderConstantProperty::Type = "property"; \ No newline at end of file diff --git a/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h b/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h new file mode 100644 index 0000000..548538d --- /dev/null +++ b/src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h @@ -0,0 +1,37 @@ +#pragma once + +#include "WallpaperEngine/Core/Projects/CProperty.h" + +#include "CShaderConstant.h" + +#include + +namespace WallpaperEngine::Core::Objects::Effects::Constants { +using namespace WallpaperEngine::Core::Projects; +/** + * Shader constant that comes from a property + */ +class CShaderConstantProperty : public CShaderConstant { + public: + // TODO: SUPPORT DEFAULT VALUE? + explicit CShaderConstantProperty (const CProperty* property); + + /** + * @return The property this points to + */ + [[nodiscard]] const CProperty* getProperty () const; + + /** + * Type string indicator + */ + static const std::string Type; + + [[nodiscard]] std::string toString () const override; + + protected: + /** + * The backing property + */ + const CProperty* m_property; +}; +} // namespace WallpaperEngine::Core::Objects::Effects::Constants diff --git a/src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.cpp b/src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.cpp index 01cfb93..d6ef058 100644 --- a/src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.cpp +++ b/src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.cpp @@ -66,24 +66,21 @@ bool CUserSettingBoolean::getDefaultValue () const { return this->m_default; } -bool CUserSettingBoolean::processValue (const std::vector& properties) const { +bool CUserSettingBoolean::processValue (const std::map& properties) const { if (!this->m_hasSource && !this->m_hasCondition) return this->getDefaultValue (); - for (const auto cur : properties) { - if (cur->getName () != this->m_source) - continue; + const auto property = properties.find (this->m_source); + if (property != properties.end ()) { if (!this->m_hasCondition) { - if (cur->is ()) - return cur->as ()->getValue (); - - sLog.exception ("Property without condition must match type boolean"); + if (property->second->is ()) + return property->second->as ()->getValue (); } // TODO: properly validate this as the combos might be more than just strings? - if (cur->is ()) - return cur->as ()->getValue () == this->m_expectedValue; + if (property->second->is ()) + return property->second->as ()->getValue () == this->m_expectedValue; sLog.exception ("Boolean property with condition doesn't match against combo value"); } diff --git a/src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h b/src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h index 1aa88c5..3c59902 100644 --- a/src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h +++ b/src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h @@ -15,7 +15,7 @@ class CUserSettingBoolean : public CUserSettingValue { static const CUserSettingBoolean* fromScalar (const bool value); static std::string Type; - [[nodiscard]] bool processValue (const std::vector& properties) const; + [[nodiscard]] bool processValue (const std::map& properties) const; [[nodiscard]] bool getDefaultValue () const; private: diff --git a/src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.cpp b/src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.cpp index bca4fc3..fe13cba 100644 --- a/src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.cpp +++ b/src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.cpp @@ -63,17 +63,16 @@ double CUserSettingFloat::getDefaultValue () const { return this->m_default; } -double CUserSettingFloat::processValue (const std::vector& properties) const { +double CUserSettingFloat::processValue (const std::map& properties) const { if (!this->m_hasSource && !this->m_hasCondition) return this->getDefaultValue (); - for (const auto cur : properties) { - if (cur->getName () != this->m_source) - continue; + const auto property = properties.find (this->m_source); + if (property != properties.end ()) { if (!this->m_hasCondition) { - if (cur->is ()) - return cur->as ()->getValue (); + if (property->second->is ()) + return property->second->as ()->getValue (); sLog.exception ("Property without condition must match type (slider)"); } diff --git a/src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.h b/src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.h index c926a71..988642a 100644 --- a/src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.h +++ b/src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.h @@ -15,7 +15,7 @@ class CUserSettingFloat : public CUserSettingValue { static const CUserSettingFloat* fromScalar (const double value); static std::string Type; - [[nodiscard]] double processValue (const std::vector& properties) const; + [[nodiscard]] double processValue (const std::map& properties) const; [[nodiscard]] double getDefaultValue () const; private: diff --git a/src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.cpp b/src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.cpp index 22f2ccc..4934a3c 100644 --- a/src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.cpp +++ b/src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.cpp @@ -64,20 +64,19 @@ const glm::vec3& CUserSettingVector3::getDefaultValue () const { return this->m_default; } -const glm::vec3& CUserSettingVector3::processValue (const std::vector& properties) const { +const glm::vec3& CUserSettingVector3::processValue (const std::map& properties) const { if (!this->m_hasSource && !this->m_hasCondition) return this->getDefaultValue (); - for (const auto cur : properties) { - if (cur->getName () != this->m_source) - continue; + const auto property = properties.find (this->m_source); + if (property != properties.end ()) { if (!this->m_hasCondition) { - if (cur->is ()) - return cur->as ()->getValue (); - if (cur->is ()) - return {cur->as ()->getValue (), cur->as ()->getValue (), - cur->as ()->getValue ()}; + if (property->second->is ()) + return property->second->as ()->getValue (); + if (property->second->is ()) + return {property->second->as ()->getValue (), property->second->as ()->getValue (), + property->second->as ()->getValue ()}; sLog.exception ("Property without condition must match type (vector3)"); } diff --git a/src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.h b/src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.h index c5230f3..e52c9d2 100644 --- a/src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.h +++ b/src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.h @@ -17,7 +17,7 @@ class CUserSettingVector3 : public CUserSettingValue { static const CUserSettingVector3* fromScalar (const glm::vec3 value); static std::string Type; - [[nodiscard]] const glm::vec3& processValue (const std::vector& properties) const; + [[nodiscard]] const glm::vec3& processValue (const std::map& properties) const; [[nodiscard]] const glm::vec3& getDefaultValue () const; private: diff --git a/src/WallpaperEngine/Render/Objects/CImage.cpp b/src/WallpaperEngine/Render/Objects/CImage.cpp index 1cf4614..6352491 100644 --- a/src/WallpaperEngine/Render/Objects/CImage.cpp +++ b/src/WallpaperEngine/Render/Objects/CImage.cpp @@ -103,12 +103,10 @@ CImage::CImage (Wallpapers::CScene* scene, const Core::Objects::CImage* image) : this->m_currentMainFBO = this->m_mainFBO = scene->createFBO (nameA.str (), ITexture::TextureFormat::ARGB8888, this->m_texture->getFlags (), 1, - this->m_texture->getRealWidth (), this->m_texture->getRealHeight (), - this->m_texture->getRealWidth (), this->m_texture->getRealHeight ()); + size.x, size.y, size.x, size.y); this->m_currentSubFBO = this->m_subFBO = scene->createFBO (nameB.str (), ITexture::TextureFormat::ARGB8888, this->m_texture->getFlags (), 1, - this->m_texture->getRealWidth (), this->m_texture->getRealHeight (), - this->m_texture->getRealWidth (), this->m_texture->getRealHeight ()); + size.x, size.y, size.x, size.y); // build a list of vertices, these might need some change later (or maybe invert the camera) GLfloat sceneSpacePosition [] = {this->m_pos.x, this->m_pos.y, 0.0f, this->m_pos.x, this->m_pos.w, 0.0f, diff --git a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp index c6398e0..e3aa57b 100644 --- a/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp +++ b/src/WallpaperEngine/Render/Objects/Effects/CPass.cpp @@ -2,6 +2,12 @@ #include "WallpaperEngine/Render/CFBO.h" #include +#include "WallpaperEngine/Core/Projects/CProperty.h" +#include "WallpaperEngine/Core/Projects/CPropertyColor.h" +#include "WallpaperEngine/Core/Projects/CPropertyCombo.h" +#include "WallpaperEngine/Core/Projects/CPropertySlider.h" +#include "WallpaperEngine/Core/Projects/CPropertyBoolean.h" + #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h" #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h" #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableInteger.h" @@ -12,7 +18,10 @@ #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h" +#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector2.h" +#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.h" #include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h" +#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h" #include "WallpaperEngine/Logging/CLog.h" using namespace WallpaperEngine::Core::Objects::Effects::Constants; @@ -613,7 +622,7 @@ template void CPass::addUniform (const std::string& name, UniformTy T* newValue = new T (value); // uniform found, add it to the list - this->m_uniforms.insert (std::make_pair (name, new UniformEntry (id, name, type, newValue, 1))); + this->m_uniforms.insert_or_assign (name, new UniformEntry (id, name, type, newValue, 1)); } template void CPass::addUniform (const std::string& name, UniformType type, T* value, int count) { @@ -625,7 +634,7 @@ template void CPass::addUniform (const std::string& name, UniformTy return; // uniform found, add it to the list - this->m_uniforms.insert (std::make_pair (name, new UniformEntry (id, name, type, value, count))); + this->m_uniforms.insert_or_assign (name, new UniformEntry (id, name, type, value, count)); } template void CPass::addUniform (const std::string& name, UniformType type, T** value) { @@ -637,8 +646,8 @@ template void CPass::addUniform (const std::string& name, UniformTy return; // uniform found, add it to the list - this->m_referenceUniforms.insert ( - std::make_pair (name, new ReferenceUniformEntry (id, name, type, reinterpret_cast (value)))); + this->m_referenceUniforms.insert_or_assign ( + name, new ReferenceUniformEntry (id, name, type, reinterpret_cast (value))); } void CPass::setupTextures () { @@ -672,6 +681,18 @@ void CPass::setupTextures () { } void CPass::setupShaderVariables () { + for (const auto& cur : this->m_shader->getVertex ().getParameters ()) + if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ()) + this->addUniform (cur); + + for (const auto& cur : this->m_shader->getVertex ().getParameters ()) + if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ()) + this->addUniform (cur); + + if (this->getMaterial ()->getImage ()->getImage ()->getName ()== "Blur") { + sLog.out("girl!"); + } + // find variables in the shaders and set the value with the constants if possible for (const auto& [name, value] : this->m_pass->getConstants ()) { const auto parameters = this->m_shader->findParameter (name); @@ -708,20 +729,25 @@ void CPass::setupShaderVariables () { auto* val = value->as (); this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y, val->getValue ()->z}); + } else if (value->is () && var->is ()) { + auto* val = value->as (); + + this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y}); + } else if (value->is ()) { + const auto property = value->as (); + + // resolve the property to a current setting + + + // resolve property to a user setting and store that value instead + // properties have different kinds of values + sLog.out("property!"); } else { sLog.exception ("Constant ", name, " type does not match pixel/vertex shader variable and cannot be converted (", value->getType (), " to ", var->getType ()); } } - - for (const auto& cur : this->m_shader->getVertex ().getParameters ()) - if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ()) - this->addUniform (cur); - - for (const auto& cur : this->m_shader->getVertex ().getParameters ()) - if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ()) - this->addUniform (cur); } // define some basic methods for the template @@ -741,6 +767,65 @@ void CPass::addUniform (CShaderVariable* value) { else if (value->is ()) this->addUniform (value->getName (), static_cast (value->as ()->getValue ())); + else + sLog.exception ("Trying to add an uniform from an unknown type: ", value->getName ()); +} + +void CPass::addUniform (CShaderVariable* value, CProperty* setting) { + // TODO: CHECK THIS? CAN WE KEEP A REF SO THE VALUES ARE AUTOMATICALLY UPDATED? + // TODO: MAYBE PROVIDE PUBLIC CASTS FOR EVERYTHING INSTEAD OF MANUALLY DOING IT EVERYWHERE + if (value->is ()) { + if (setting->is ()) { + const auto slider = setting->as (); + // sliders have to be converted to vector2 + this->addUniform (value->getName (), {slider->getValue (), slider->getValue ()}); + } else if (setting->is ()) { + const auto color = setting->as (); + // colors are vec3, we just need vec2 + this->addUniform (value->getName (), {color->getValue ().x, color->getValue ().y}); + } else { + sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value"); + this->addUniform (value); + } + } else if (value->is ()) { + if (setting->is ()) { + const auto slider = setting->as (); + + this->addUniform (value->getName (), slider->getValue ()); + } else if (setting->is()) { + const auto color = setting->as (); + + this->addUniform (value->getName (), &color->getValue ().x); + } else { + sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value"); + this->addUniform (value); + } + } else if (value->is ()) { + if (setting->is ()) { + const auto slider = setting->as (); + + this->addUniform (value->getName (), {slider->getValue (), slider->getValue (), slider->getValue ()}); + } else if (setting->is()) { + const auto color = setting->as (); + + this->addUniform (value->getName (), color->getValue ()); + } else { + sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value"); + this->addUniform (value); + } + } else if (value->is ()) { + if (setting->is ()) { + const auto slider = setting->as (); + + this->addUniform (value->getName (), {slider->getValue (), slider->getValue (), slider->getValue (), slider->getValue ()}); + } else { + sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value"); + this->addUniform (value); + } + } else { + sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value"); + this->addUniform (value); + } } void CPass::addUniform (const std::string& name, CShaderConstant* value) { @@ -749,8 +834,14 @@ void CPass::addUniform (const std::string& name, CShaderConstant* value) { this->addUniform (name, value->as ()->getValue ()); else if (value->is ()) this->addUniform (name, value->as ()->getValue ()); + else if (value->is ()) + this->addUniform (name, value->as ()->getValue ()); + else if (value->is ()) + this->addUniform (name, value->as ()->getValue ()); else if (value->is ()) this->addUniform (name, value->as ()->getValue ()); + else + sLog.exception ("Trying to add an uniform from an unknown type: ", name); } void CPass::addUniform (const std::string& name, const CShaderConstant* value) { @@ -759,8 +850,14 @@ void CPass::addUniform (const std::string& name, const CShaderConstant* value) { this->addUniform (name, value->as ()->getValue ()); else if (value->is ()) this->addUniform (name, value->as ()->getValue ()); + else if (value->is ()) + this->addUniform (name, value->as ()->getValue ()); + else if (value->is ()) + this->addUniform (name, value->as ()->getValue ()); else if (value->is ()) this->addUniform (name, value->as ()->getValue ()); + else + sLog.exception ("Trying to add an uniform from an unknown type: ", name); } void CPass::addUniform (const std::string& name, int value) { this->addUniform (name, UniformType::Integer, value); diff --git a/src/WallpaperEngine/Render/Objects/Effects/CPass.h b/src/WallpaperEngine/Render/Objects/Effects/CPass.h index 26581f4..38f5507 100644 --- a/src/WallpaperEngine/Render/Objects/Effects/CPass.h +++ b/src/WallpaperEngine/Render/Objects/Effects/CPass.h @@ -10,12 +10,13 @@ #include "WallpaperEngine/Render/Objects/Effects/CMaterial.h" #include "WallpaperEngine/Render/Shaders/CShader.h" #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h" - +#include "WallpaperEngine/Core/UserSettings/CUserSettingValue.h" #include "WallpaperEngine/Render/Helpers/CContextAware.h" namespace WallpaperEngine::Render::Objects::Effects { using namespace WallpaperEngine::Assets; using namespace WallpaperEngine::Render::Shaders::Variables; +using namespace WallpaperEngine::Core::Projects; using namespace WallpaperEngine::Core::Objects::Effects::Constants; class CMaterial; @@ -108,6 +109,7 @@ class CPass final : public Helpers::CContextAware { void setupAttributes (); void addAttribute (const std::string& name, GLint type, GLint elements, const GLuint* value); void addUniform (CShaderVariable* value); + void addUniform (CShaderVariable* value, CProperty* setting); void addUniform (const std::string& name, CShaderConstant* value); void addUniform (const std::string& name, const CShaderConstant* value); void addUniform (const std::string& name, int value); diff --git a/src/WallpaperEngine/Render/Shaders/CShader.cpp b/src/WallpaperEngine/Render/Shaders/CShader.cpp index 21ce7b6..71c6668 100644 --- a/src/WallpaperEngine/Render/Shaders/CShader.cpp +++ b/src/WallpaperEngine/Render/Shaders/CShader.cpp @@ -18,11 +18,11 @@ using namespace WallpaperEngine::Assets; namespace WallpaperEngine::Render::Shaders { CShader::CShader ( - const CContainer* container, std::string filename, std::map combos, + const CContainer* container, std::string filename, const std::map& combos, const std::map& textures, const std::map& constants ) : m_file (std::move (filename)), - m_combos (std::move(combos)), + m_combos (combos), m_passTextures (textures), m_vertex ( CGLSLContext::UnitType_Vertex, filename, container->readVertexShader (filename), @@ -30,6 +30,9 @@ CShader::CShader ( m_fragment ( CGLSLContext::UnitType_Fragment, filename, container->readFragmentShader (filename), container, constants, textures, combos) { + // link shaders between them + this->m_vertex.linkToUnit (&this->m_fragment); + this->m_fragment.linkToUnit (&this->m_vertex); } diff --git a/src/WallpaperEngine/Render/Shaders/CShader.h b/src/WallpaperEngine/Render/Shaders/CShader.h index f8c6829..a2ceef1 100644 --- a/src/WallpaperEngine/Render/Shaders/CShader.h +++ b/src/WallpaperEngine/Render/Shaders/CShader.h @@ -43,7 +43,7 @@ class CShader { */ CShader ( const CContainer* container, std::string filename, - std::map combos,const std::map& textures, + const std::map& combos,const std::map& textures, const std::map& constants); /** * @return The vertex's shader coude for OpenGL to use @@ -93,7 +93,7 @@ class CShader { /** * The combos the shader should be generated with */ - std::map m_combos; + const std::map& m_combos; /** * The list of textures the pass knows about */ diff --git a/src/WallpaperEngine/Render/Shaders/CShaderUnit.cpp b/src/WallpaperEngine/Render/Shaders/CShaderUnit.cpp index fb1b963..463af9a 100644 --- a/src/WallpaperEngine/Render/Shaders/CShaderUnit.cpp +++ b/src/WallpaperEngine/Render/Shaders/CShaderUnit.cpp @@ -79,6 +79,16 @@ void CShaderUnit::preprocess () { this->preprocessVariables (); this->preprocessIncludes (); this->preprocessRequires (); + + // replace gl_FragColor with the equivalent + std::string from = "gl_FragColor"; + std::string to = "out_FragColor"; + + size_t start_pos = 0; + while ((start_pos = this->m_preprocessed.find (from, start_pos)) != std::string::npos) { + this->m_preprocessed.replace (start_pos, from.length (), to); + start_pos += to.length (); // Handles case where 'to' is a substring of 'from' + } } void CShaderUnit::preprocessVariables () { @@ -344,6 +354,9 @@ void CShaderUnit::parseComboConfiguration (const std::string& content, int defau void CShaderUnit::parseParameterConfiguration (const std::string& type, const std::string& name, const std::string& content) { + if (name == "g_Speed") { + sLog.out("speed!"); + } json data = json::parse (content); const auto material = data.find ("material"); const auto defvalue = data.find ("default"); @@ -365,37 +378,23 @@ void CShaderUnit::parseParameterConfiguration (const std::string& type, const st // TODO: SUPPORT VALUES FOR ALL THESE TYPES if (type == "vec4") { - parameter = new Variables::CShaderVariableVector4 ( - constant == this->m_constants.end () ? WallpaperEngine::Core::aToVector4 (*defvalue) - : *constant->second->as ()->getValue ()); + parameter = new Variables::CShaderVariableVector4(WallpaperEngine::Core::aToVector4 (*defvalue)); } else if (type == "vec3") { - parameter = new Variables::CShaderVariableVector3 ( - constant == this->m_constants.end () ? WallpaperEngine::Core::aToVector3 (*defvalue) - : *constant->second->as ()->getValue ()); + parameter = new Variables::CShaderVariableVector3 (WallpaperEngine::Core::aToVector3 (*defvalue)); } else if (type == "vec2") { parameter = new Variables::CShaderVariableVector2 (WallpaperEngine::Core::aToVector2 (*defvalue)); } else if (type == "float") { - float value = 0; - - if (constant == this->m_constants.end ()) - value = defvalue->get (); - else if (constant->second->is ()) - value = *constant->second->as ()->getValue (); - else if (constant->second->is ()) - value = *constant->second->as ()->getValue (); - - parameter = new Variables::CShaderVariableFloat (value); + if (defvalue->is_string ()) { + parameter = new Variables::CShaderVariableFloat (strtof32 ((defvalue->get ()).c_str (), nullptr)); + } else { + parameter = new Variables::CShaderVariableFloat (*defvalue); + } } else if (type == "int") { - int value = 0; - - if (constant == this->m_constants.end ()) - value = defvalue->get (); - else if (constant->second->is ()) - value = *constant->second->as ()->getValue (); - else if (constant->second->is ()) - value = *constant->second->as ()->getValue (); - - parameter = new Variables::CShaderVariableInteger (value); + if (defvalue->is_string ()) { + parameter = new Variables::CShaderVariableInteger (strtol((defvalue->get ()).c_str (), nullptr, 10)); + } else { + parameter = new Variables::CShaderVariableInteger (*defvalue); + } } else if (type == "sampler2D" || type == "sampler2DComparison") { // samplers can have special requirements, check what sampler we're working with and create definitions // if needed @@ -410,55 +409,75 @@ void CShaderUnit::parseParameterConfiguration (const std::string& type, const st if (combo != data.end ()) { // if the texture exists (and is not null), add to the combo auto texture = this->m_textures.find (index); - bool comboValue = true; + bool isRequired = false; + int comboValue = 1; - if (textureName == data.end () && texture == this->m_textures.end ()) { - // is this required? - if (require == data.end ()) { - // if no require information we assume this one is always required, so signal it as such - //sLog.exception ("Shader ", this->m_file, " requires a texture that is not present"); - comboValue = false; - } - - // some require conditions are set, validate these - if (requireany == data.end () || !requireany->get ()) { - // all values have to exist for this to be required - for (const auto& item : require->items ()) { - const std::string& macro = item.key (); - const auto it = this->m_combos.find (macro); - - // these can not exist and that'd be fine, we just care about the values - if (it != this->m_combos.end () && it->second == item.value ()) { - continue; - } - - comboValue = false; - break; - } - } else { - comboValue = false; + if (texture != this->m_textures.end ()) { + // nothing extra to do, the texture exists, the combo must be set + // these tend to not have default value + isRequired = true; + } else if (require != data.end ()) { + // this is required based on certain conditions + if (requireany != data.end () && requireany->get ()) { // any of the values set are valid, check for them for (const auto& item : require->items ()) { const std::string& macro = item.key (); const auto it = this->m_combos.find (macro); - // these can not exist and that'd be fine, we just care about the values + // if any of the values matched, this option is required if (it == this->m_combos.end () || it->second != item.value ()) { - continue; + isRequired = true; + break; } + } + } else { + isRequired = true; - comboValue = true; + // all values must match for it to be required + for (const auto& item : require->items ()) { + const std::string& macro = item.key (); + const auto it = this->m_combos.find (macro); + + // these can not exist and that'd be fine, we just care about the values + if (it != this->m_combos.end () && it->second == item.value ()) { + isRequired = false; + break; + } } } } - // add the new combo to the list - this->m_discoveredCombos.insert (std::make_pair (*combo, comboValue)); + if (isRequired && texture == this->m_textures.end ()) { + if (defvalue == data.end ()) { + isRequired = false; + } else { + // is the combo registered already? + // if not, add it with the default value + const auto combo_it = this->m_combos.find (*combo); - // textures linked to combos need to be tracked too - if (this->m_usedCombos.find (*combo) == this->m_usedCombos.end ()) - this->m_usedCombos.insert (std::make_pair (*combo, true)); + // there's already a combo providing this value, so it doesn't need to be added + if (combo_it != this->m_combos.end ()) { + isRequired = false; + // otherwise a default value must be used + } else if (defvalue->is_string ()) { + comboValue = strtol (defvalue->get ().c_str (), nullptr, 10); + } else if (defvalue->is_number()) { + comboValue = *defvalue; + } else { + sLog.exception ("Cannot determine default value for combo ", combo->get (), " because it's not specified by the shader and is not given a default value: ", this->m_file); + } + } + } + + if (isRequired) { + // add the new combo to the list + this->m_discoveredCombos.insert (std::make_pair (*combo, comboValue)); + + // textures linked to combos need to be tracked too + if (this->m_usedCombos.find (*combo) == this->m_usedCombos.end ()) + this->m_usedCombos.insert (std::make_pair (*combo, true)); + } } if (textureName != data.end ()) @@ -471,7 +490,7 @@ void CShaderUnit::parseParameterConfiguration (const std::string& type, const st return; } - if (material != data.end ()) { + if (material != data.end () && parameter != nullptr) { parameter->setIdentifierName (*material); parameter->setName (name);