#pragma once #include "EditorAttachment.hpp" #include "RcPtr.hpp" #include "Shader.hpp" #include "Texture.hpp" #include #include #include #include #include #include #include #include #include class MaterialManager; class Material : public RefCounted { public: // NOTE: public for internal helpers and editor // NOTE: specialize between scalar vs matrix vs vector to save memory struct ScalarUniform { union { float floatValue; int32_t intValue; uint32_t uintValue; }; GLenum actualType; /* Saves 'name' */ int infoUniformIndex; /* Transient */ GLint location; }; struct VectorUniform { float value[4]; int actualLength; /* Saves 'name' */ int infoUniformIndex; /* Transient */ GLint location; }; struct MatrixUniform { float value[16]; int actualWidth; int actualHeight; /* Saves 'name' */ int infoUniformIndex; /* Transient */ GLint location; }; struct TextureUniform { RcPtr value; /* Saves 'name' */ int infoUniformIndex; /* Transient */ GLint location; }; std::string mName; std::unique_ptr mEditorAttachment; RcPtr mShader; std::vector mBoundScalars; std::vector mBoundVectors; std::vector mBoundMatrices; std::vector mBoundTextures; public: // NOTE: constructs invalid object Material() = default; Material(Shader* shader, std::string name = ""); void SetFloat(const char* name, float value); void SetInt(const char* name, int32_t value); void SetUInt(const char* name, uint32_t value); /// Instanciated for length == 1, 2, 3, 4 template void SetVector(const char* name, const glm::vec& vec); /// Instanciated for sizes (2,2) (3,3) (4,4) (2,3) (3,2) (2,4) (4,2) (3,4) (4,3) template void SetMatrix(const char* name, const glm::mat& mat); void SetTexture(const char* name, Texture* texture); std::span GetVectors() const; std::span GetMatrices() const; std::span GetTextures() const; Shader* GetShader() const; void SetShader(Shader* shader); const std::string& GetName() const; bool IsAnnoymous() const; bool IsValid() const; void UseUniforms() const; EditorAttachment* GetEditorAttachment() const { return mEditorAttachment.get(); } void SetEditorAttachment(EditorAttachment* attachment) { mEditorAttachment.reset(attachment); } void GetDesignatedPath(char* buffer, int bufferSize); std::filesystem::path GetDesignatedPath(); bool SaveToFile(const std::filesystem::path& filePath) const; bool LoadFromFile(const std::filesystem::path& filePath); }; class MaterialManager { public: static inline MaterialManager* instance = nullptr; private: absl::flat_hash_map> mMaterials; public: void DiscoverMaterials(); std::pair SaveMaterial(Material* mat); void DeleteMaterial(Material* mat, bool onDisk = false); Material* LoadMaterial(std::string_view name); bool RenameMaterial(Material* mat, std::string newName); const auto& GetMaterials() const { return mMaterials; } Material* FindMaterial(std::string_view name); };