#include "MaterialParser.h" #include "TextureParser.h" #include "WallpaperEngine/Data/Model/Material.h" #include "WallpaperEngine/Data/Model/Project.h" #include "WallpaperEngine/Data/Parsers/ShaderConstantParser.h" #include "WallpaperEngine/FileSystem/Container.h" using namespace WallpaperEngine::Data::Parsers; using namespace WallpaperEngine::Data::Model; MaterialUniquePtr MaterialParser::load (const Project& project, const std::string& filename) { const auto materialJson = JSON::parseAsset (project.assetLocator->readString (filename)); return parse (materialJson, filename, project); } MaterialUniquePtr MaterialParser::parse (const JSON& it, const std::string& filename, const Project& project) { return std::make_unique (Material { .filename = filename, .passes = parsePasses (it.require ("passes", "Material must have passes to render"), project), }); } std::vector MaterialParser::parsePasses (const JSON& it, const Project& project) { std::vector result = {}; if (!it.is_array ()) { return result; } for (const auto& cur : it) { result.push_back (parsePass (cur, project)); } return result; } MaterialPassUniquePtr MaterialParser::parsePass (const JSON& it, const Project& project) { const auto textures = it.optional ("textures"); const auto usertextures = it.optional ("usertextures"); const auto combos = it.optional ("combos"); const auto constants = it.optional ("constantshadervalues"); return std::make_unique (MaterialPass { // TODO: avoid this std::string construction .blending = parseBlendMode (it.optional ("blending", std::string ("normal"))), // left unknown when missing, which draws like nocull/disabled, 3D models pick their own defaults .cullmode = it.contains ("cullmode") ? parseCullMode (it["cullmode"]) : CullingMode_Unknown, .depthtest = it.contains ("depthtest") ? parseDepthtestMode (it["depthtest"]) : DepthtestMode_Unknown, .depthwrite = it.contains ("depthwrite") ? parseDepthwriteMode (it["depthwrite"]) : DepthwriteMode_Unknown, .shader = it.require ("shader", "Material pass must have a shader"), .textures = textures.has_value () ? TextureParser::parseTextureMap (*textures) : TextureMap {}, .usertextures = usertextures.has_value () ? TextureParser::parseTextureMap (*usertextures) : TextureMap {}, .combos = combos.has_value () ? parseCombos (*combos) : ComboMap {}, .constants = constants.has_value () ? ShaderConstantParser::parse (*constants, project) : ShaderConstantMap {}, }); } std::map MaterialParser::parseCombos (const JSON& it) { std::map result = {}; if (!it.is_object ()) { return result; } for (const auto& cur : it.items ()) { result.emplace (cur.key (), cur.value ()); } return result; } BlendingMode MaterialParser::parseBlendMode (const std::string& mode) { if (mode == "normal") { return BlendingMode_Normal; } if (mode == "additive") { return BlendingMode_Additive; } if (mode == "translucent") { return BlendingMode_Translucent; } sLog.error ("Unknown blending mode: ", mode, " defaulting to normal"); return BlendingMode_Normal; } CullingMode MaterialParser::parseCullMode (const std::string& mode) { if (mode == "nocull") { return CullingMode_Disable; } if (mode == "normal") { return CullingMode_Normal; } sLog.error ("Unknown culling mode: ", mode, " defaulting to nocull"); return CullingMode_Disable; } DepthtestMode MaterialParser::parseDepthtestMode (const std::string& mode) { if (mode == "disabled") { return DepthtestMode_Disabled; } if (mode == "enabled") { return DepthtestMode_Enabled; } sLog.error ("Unknown depthtest mode: ", mode, " defaulting to disabled"); return DepthtestMode_Disabled; } DepthwriteMode MaterialParser::parseDepthwriteMode (const std::string& mode) { if (mode == "disabled") { return DepthwriteMode_Disabled; } if (mode == "enabled") { return DepthwriteMode_Enabled; } sLog.error ("Unknown depthwrite mode: ", mode, " defaulting to disabled"); return DepthwriteMode_Disabled; }