1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
#include "ShaderLibrary.h"
#include <utility>
#include "iimage.h"
#include "itextstream.h"
#include "ShaderTemplate.h"
namespace shaders
{
std::shared_ptr<ShaderTemplate> ShaderLibrary::getTemplate(const std::string& name)
{
auto decl = std::static_pointer_cast<ShaderTemplate>(
GlobalDeclarationManager().findDeclaration(decl::Type::Material, name));
if (decl)
{
return decl;
}
// The shader definition hasn't been found, let's check if the name
// refers to a file in the VFS
if (auto img = GlobalImageLoader().imageFromVFS(name); img)
{
// Insert a new declaration, creating a diffusemap with that image
decl = std::static_pointer_cast<ShaderTemplate>(
GlobalDeclarationManager().findOrCreateDeclaration(decl::Type::Material, name));
auto imgExpr = std::make_shared<ImageExpression>(name);
decl->addLayer(IShaderLayer::DIFFUSE, imgExpr);
decl->setFileInfo(vfs::FileInfo("materials/", "_autogenerated_by_darkradiant_.mtr", vfs::Visibility::HIDDEN));
return decl;
}
rWarning() << "ShaderLibrary: definition not found: " << name << std::endl;
// Insert a new declaration, creating a diffusemap with that image
decl = std::static_pointer_cast<ShaderTemplate>(
GlobalDeclarationManager().findOrCreateDeclaration(decl::Type::Material, name));
decl->setDescription("This material is missing and has been auto-generated by DarkRadiant");
// Make the definition VFS-visible to let them show in MediaBrowser (#5475)
decl->setFileInfo(vfs::FileInfo("materials/", "_autogenerated_by_darkradiant_.mtr", vfs::Visibility::NORMAL));
return decl;
}
bool ShaderLibrary::definitionExists(const std::string& name) const
{
return GlobalDeclarationManager().findDeclaration(decl::Type::Material, name) != nullptr;
}
void ShaderLibrary::copyDefinition(const std::string& nameOfOriginal, const std::string& nameOfCopy)
{
// These need to be checked by the caller
assert(definitionExists(nameOfOriginal));
assert(!definitionExists(nameOfCopy));
auto originalDecl = GlobalDeclarationManager().findDeclaration(decl::Type::Material, nameOfOriginal);
auto decl = GlobalDeclarationManager().findOrCreateDeclaration(decl::Type::Material, nameOfCopy);
// Replace the syntax block of the target with the one of the original
auto syntax = originalDecl->getBlockSyntax();
syntax.name = nameOfCopy;
syntax.fileInfo = vfs::FileInfo{ "", "", vfs::Visibility::HIDDEN };
decl->setBlockSyntax(syntax);
}
bool ShaderLibrary::renameDefinition(const std::string& oldName, const std::string& newName)
{
auto result = GlobalDeclarationManager().renameDeclaration(decl::Type::Material, oldName, newName);
// Rename in shaders table (if existing)
if (result && _shaders.count(oldName) > 0)
{
auto extractedShader = _shaders.extract(oldName);
extractedShader.key() = newName;
// Insert it under the new name before setting the CShader instance's name
// the observing OpenGLShader instance will request the material to reconstruct itself
// If the new name is not present at that point, the library will create a default material.
auto insertedShader = _shaders.insert(std::move(extractedShader));
// Rename the CShader instance
insertedShader.position->second->setName(newName);
}
return result;
}
void ShaderLibrary::removeDefinition(const std::string& name)
{
assert(definitionExists(name));
GlobalDeclarationManager().removeDeclaration(decl::Type::Material, name);
_shaders.erase(name);
}
CShaderPtr ShaderLibrary::findShader(const std::string& name)
{
// Try to lookup the shader in the active shaders list
auto existing = _shaders.find(name);
if (existing != _shaders.end())
{
// A shader has been found, return its pointer
return existing->second;
}
// No shader has been found, retrieve its declaration (may also be a dummy one)
auto decl = getTemplate(name);
// Construct a new shader object with this def and insert it into the map
return _shaders.emplace(name, std::make_shared<CShader>(name, decl)).first->second;
}
void ShaderLibrary::clear()
{
_shaders.clear();
}
void ShaderLibrary::foreachShaderName(const ShaderNameCallback& callback)
{
GlobalDeclarationManager().foreachDeclaration(decl::Type::Material, [&](const decl::IDeclaration::Ptr& decl)
{
if (decl->getBlockSyntax().fileInfo.visibility == vfs::Visibility::NORMAL)
{
callback(decl->getDeclName());
}
});
}
void ShaderLibrary::foreachShader(const std::function<void(const CShaderPtr&)>& func)
{
for (const ShaderMap::value_type& pair : _shaders)
{
func(pair.second);
}
}
} // namespace shaders
|