/
ShaderFileLoader.h
125 lines (100 loc) · 3.66 KB
/
ShaderFileLoader.h
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
#pragma once
#include "iarchive.h"
#include "ifilesystem.h"
#include "TableDefinition.h"
#include "ShaderTemplate.h"
#include "ShaderDefinition.h"
#include "parser/DefBlockTokeniser.h"
#include "string/replace.h"
namespace shaders
{
// VFS functor class which loads material (mtr) files.
template<typename ShaderLibrary_T> class ShaderFileLoader
{
// The VFS module to provide shader files
vfs::VirtualFileSystem& _vfs;
ShaderLibrary_T& _library;
// List of shader definition files to parse
std::vector<vfs::FileInfo> _files;
private:
// Parse a shader file with the given contents and filename
void parseShaderFile(std::istream& inStr, const vfs::FileInfo& fileInfo)
{
// Parse the file with a blocktokeniser, the actual block contents
// will be parsed separately.
parser::BasicDefBlockTokeniser<std::istream> tokeniser(inStr);
while (tokeniser.hasMoreBlocks())
{
// Get the next block
parser::BlockTokeniser::Block block = tokeniser.nextBlock();
// Skip tables
if (block.name.substr(0, 5) == "table")
{
std::string tableName = block.name.substr(6);
if (tableName.empty())
{
rError() << "[shaders] " << fileInfo.name << ": Missing table name." << std::endl;
continue;
}
TableDefinitionPtr table(new TableDefinition(tableName, block.contents));
if (!_library.addTableDefinition(table))
{
rError() << "[shaders] " << fileInfo.name
<< ": table " << tableName << " already defined." << std::endl;
}
continue;
}
else if (block.name.substr(0, 5) == "skin ")
{
continue; // skip skin definition
}
else if (block.name.substr(0, 9) == "particle ")
{
continue; // skip particle definition
}
string::replace_all(block.name, "\\", "/"); // use forward slashes
ShaderTemplatePtr shaderTemplate(new ShaderTemplate(block.name, block.contents));
// Construct the ShaderDefinition wrapper class
ShaderDefinition def(shaderTemplate, fileInfo.name);
// Insert into the definitions map, if not already present
if (!_library.addDefinition(block.name, def))
{
rError() << "[shaders] " << fileInfo.name
<< ": shader " << block.name << " already defined." << std::endl;
}
}
}
public:
/// Construct and initialise the ShaderFileLoader
ShaderFileLoader(vfs::VirtualFileSystem& fs, ShaderLibrary_T& library,
const std::string& basedir,
const std::string& extension = "mtr")
: _vfs(fs), _library(library)
{
_files.reserve(200);
// Walk the VFS and populate our files list
_vfs.forEachFile(
basedir, extension,
[this](const vfs::FileInfo& fi) { _files.push_back(fi); },
0
);
}
void parseFiles()
{
for (const vfs::FileInfo& fileInfo: _files)
{
// Open the file
ArchiveTextFilePtr file = _vfs.openTextFile(fileInfo.fullPath());
if (file != nullptr)
{
std::istream is(&(file->getInputStream()));
parseShaderFile(is, fileInfo);
}
else
{
throw std::runtime_error("Unable to read shaderfile: " + fileInfo.name);
}
}
}
};
}