mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 02:56:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef OPENMW_COMPONENTS_SETTINGS_SHADERMANAGER_H
 | |
| #define OPENMW_COMPONENTS_SETTINGS_SHADERMANAGER_H
 | |
| 
 | |
| #include <filesystem>
 | |
| #include <fstream>
 | |
| #include <optional>
 | |
| #include <unordered_map>
 | |
| #include <vector>
 | |
| 
 | |
| #include <yaml-cpp/yaml.h>
 | |
| 
 | |
| #include <osg/Vec2f>
 | |
| #include <osg/Vec3f>
 | |
| #include <osg/Vec4f>
 | |
| 
 | |
| #include <components/debug/debuglog.hpp>
 | |
| #include <components/files/conversion.hpp>
 | |
| #include <components/serialization/osgyaml.hpp>
 | |
| 
 | |
| namespace Settings
 | |
| {
 | |
|     /*
 | |
|      * Manages the shader.yaml file which is auto-generated and lives next to settings.cfg.
 | |
|      * This YAML file is simply a mapping of technique name to a list of uniforms and their values.
 | |
|      * Currently only vec2f, vec3f, vec4f, int, and float uniforms are supported.
 | |
|      *
 | |
|      * config:
 | |
|      *   TECHNIQUE:
 | |
|      *    MY_FLOAT: 10.34
 | |
|      *    MY_VEC2: [0.23, 0.34]
 | |
|      *   TECHNIQUE2:
 | |
|      *    MY_VEC3: [0.22, 0.33, 0.20]
 | |
|      */
 | |
|     class ShaderManager
 | |
|     {
 | |
|     public:
 | |
|         enum class Mode
 | |
|         {
 | |
|             Normal,
 | |
|             Debug
 | |
|         };
 | |
| 
 | |
|         ShaderManager() = default;
 | |
|         ShaderManager(ShaderManager const&) = delete;
 | |
|         void operator=(ShaderManager const&) = delete;
 | |
| 
 | |
|         static ShaderManager& get()
 | |
|         {
 | |
|             static ShaderManager instance;
 | |
|             return instance;
 | |
|         }
 | |
| 
 | |
|         Mode getMode() { return mMode; }
 | |
| 
 | |
|         void setMode(Mode mode) { mMode = mode; }
 | |
| 
 | |
|         const YAML::Node& getRoot() { return mData; }
 | |
| 
 | |
|         template <class T>
 | |
|         bool setValue(const std::string& tname, const std::string& uname, const T& value)
 | |
|         {
 | |
|             if (mData.IsNull())
 | |
|             {
 | |
|                 Log(Debug::Warning) << "Failed setting " << tname << ", " << uname
 | |
|                                     << " : shader settings failed to load";
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             mData["config"][tname][uname] = value;
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         template <class T>
 | |
|         std::optional<T> getValue(const std::string& tname, const std::string& uname)
 | |
|         {
 | |
|             if (mData.IsNull())
 | |
|             {
 | |
|                 Log(Debug::Warning) << "Failed getting " << tname << ", " << uname
 | |
|                                     << " : shader settings failed to load";
 | |
|                 return std::nullopt;
 | |
|             }
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 auto value = mData["config"][tname][uname];
 | |
| 
 | |
|                 if (!value)
 | |
|                     return std::nullopt;
 | |
| 
 | |
|                 return value.as<T>();
 | |
|             }
 | |
|             catch (const YAML::BadConversion&)
 | |
|             {
 | |
|                 Log(Debug::Warning) << "Failed retrieving " << tname << ", " << uname
 | |
|                                     << " : mismatched types in config file.";
 | |
|             }
 | |
| 
 | |
|             return std::nullopt;
 | |
|         }
 | |
| 
 | |
|         bool load(const std::filesystem::path& path)
 | |
|         {
 | |
|             mData = YAML::Null;
 | |
|             mPath = path;
 | |
| 
 | |
|             Log(Debug::Info) << "Loading shader settings file: " << mPath;
 | |
| 
 | |
|             if (!std::filesystem::exists(mPath))
 | |
|             {
 | |
|                 std::ofstream fout(mPath);
 | |
|                 if (!fout)
 | |
|                 {
 | |
|                     Log(Debug::Error) << "Failed creating shader settings file: " << mPath;
 | |
|                     return false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 std::ifstream file{ mPath };
 | |
|                 mData = YAML::Load(file);
 | |
|                 mData.SetStyle(YAML::EmitterStyle::Block);
 | |
| 
 | |
|                 if (!mData["config"])
 | |
|                     mData["config"] = YAML::Node();
 | |
| 
 | |
|                 return true;
 | |
|             }
 | |
|             catch (const YAML::Exception& e)
 | |
|             {
 | |
|                 Log(Debug::Error) << "Shader settings failed to load, " << e.msg;
 | |
|             }
 | |
| 
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bool save()
 | |
|         {
 | |
|             if (mData.IsNull())
 | |
|             {
 | |
|                 Log(Debug::Error) << "Shader settings failed to load, settings will not be saved: " << mPath;
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             Log(Debug::Info) << "Saving shader settings file: " << mPath;
 | |
| 
 | |
|             YAML::Emitter out;
 | |
|             out.SetMapFormat(YAML::Block);
 | |
|             out << mData;
 | |
| 
 | |
|             std::ofstream fout(mPath);
 | |
|             fout << out.c_str();
 | |
| 
 | |
|             if (!fout)
 | |
|             {
 | |
|                 Log(Debug::Error) << "Failed saving shader settings file: " << mPath;
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|     private:
 | |
|         std::filesystem::path mPath;
 | |
|         YAML::Node mData;
 | |
|         Mode mMode = Mode::Normal;
 | |
|     };
 | |
| }
 | |
| 
 | |
| #endif
 |