Commit bcada566 authored by Robert Menzel's avatar Robert Menzel

support added for #pragma ACGLimport

parent 327f86f3
......@@ -69,6 +69,9 @@ public:
bool setSources (const std::vector<std::string> &_sources, bool _checkForCompileErrors = true );
protected:
// could get reactivated if needed, might get removed later (thus protected):
bool setFromFileNoImportParsing(const std::string& _filename);
bool compile () const;
// get a log and a bool whether the log contains an error (or just a warning), not done
// automatically by compile() but called by all public source setting functions:
......@@ -82,6 +85,26 @@ protected:
GLenum mType;
};
class ShaderParser
{
public:
ShaderParser( const std::string &_filename );
std::vector< std::string > getSources() { return mSources; }
std::string getFileNamesPrintable();
private:
void readin( const std::string &_filename );
bool lineContainsVersion( const std::string &line, unsigned int &version);
bool lineContainsImport( const std::string &line, std::string &filename);
std::vector< std::string > mSources;
std::vector< std::string > mSourceFileNames;
unsigned int mMaxVersion;
};
ACGL_SMARTPOINTER_TYPEDEFS(Shader)
} // OpenGL
......
......@@ -32,6 +32,9 @@ namespace StringOperations
return false;
_path = _full.substr(0,found);
_fileOrFolder = _full.substr(found+1);
if(_path.size() > 2 && _path[0] == '.' && _path[1] == '/') {
_path = _path.substr(2, _path.size()-2);
}
return true;
}
......
......@@ -10,12 +10,14 @@
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace ACGL::Base;
using namespace ACGL::Utils;
using namespace ACGL::OpenGL;
bool Shader::setFromFile(const std::string& _filename)
bool Shader::setFromFileNoImportParsing(const std::string& _filename)
{
std::string line = "";
std::string fileContent = "";
......@@ -52,6 +54,26 @@ bool Shader::setFromFile(const std::string& _filename)
return !compileErrors; // return true iff there were no errors
}
bool Shader::setFromFile(const std::string& _filename)
{
ShaderParser sp( _filename );
bool compileErrors = true;
if ( setSources( sp.getSources(), false) ) { // don't check for errors, we will do that on our own:
std::string compileLog;
getCompileLog( compileLog, compileErrors );
if (compileLog.size() > 0) {
if (compileErrors) {
error() << "\nIn files: \n" << sp.getFileNamesPrintable() << compileLog << "\n" << std::endl;
} else {
warning() << "\nIn files: \n" << sp.getFileNamesPrintable() << compileLog << "\n" << std::endl;
}
}
}
return !compileErrors; // return true iff there were no errors
}
bool Shader::setSource(const std::string& _source, bool _checkForCompileErrors)
{
const char *pProgramString = _source.c_str();
......@@ -151,3 +173,137 @@ void Shader::getCompileLog( std::string &_log, bool &_wasErrorLog ) const
_log = "";
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ShaderParser::ShaderParser( const std::string &_filename )
{
mMaxVersion = 110;
mSources.push_back( "#version 330\n" );
std::string path, file;
StringOperations::splitLastFileOrFolder( _filename, path, file );
//readin( "./"+path+"/"+file );
readin( _filename );
if (mMaxVersion > 110) {
mSources[0] = "#version "+StringOperations::toString(mMaxVersion)+"\n";
}
}
bool ShaderParser::lineContainsVersion( const std::string &line, unsigned int &version)
{
std::vector< std::string > token = StringOperations::split( line, ' ' );
if (token.size() >= 2 && token[0] == "#version") {
version = StringOperations::to<unsigned int>(token[1]);
//debug() << "string " << line << " -> version " << version << std::endl;
return true;
}
return false;
}
bool ShaderParser::lineContainsImport( const std::string &line, std::string &filename)
{
std::vector< std::string > token = StringOperations::split( line, ' ' );
if (token.size() >= 3 && token[0] == "#pragma" && token[1] == "ACGLimport") {
if (token[2].size() >= 2) {
size_t startName = line.find('"',0);
if (startName == std::string::npos) return false;
size_t endName = line.find('"',startName+1);
if (endName == std::string::npos) return false;
filename = line.substr(startName+1, endName-startName-1); // remove the ""
//debug() << "string " << line << " -> import " << filename << std::endl;
return true;
}
}
return false;
}
std::string ShaderParser::getFileNamesPrintable()
{
std::string rString;
for (size_t i = 0; i < mSourceFileNames.size(); ++i) {
rString += " " + StringOperations::toString(i+1) + " " + mSourceFileNames[i] + "\n";
}
return rString;
}
void ShaderParser::readin( const std::string &_filename )
{
std::string line = "";
std::ifstream fileStream(_filename.c_str(), std::ifstream::in);
unsigned int lineNumber = 1;
mSourceFileNames.push_back( _filename );
unsigned int fileNumber = mSourceFileNames.size();
// define the file and line number to get correct errors from the shader compiler:
std::string fileContent = "#line "+StringOperations::toString(lineNumber)+" "+StringOperations::toString(fileNumber)+"\n";
//debug() << "parse file " << _filename << std::endl;
if(fileStream.is_open())
{
while (fileStream.good())
{
std::getline(fileStream,line);
unsigned int version;
std::string fileToImport;
if ( lineContainsVersion(line, version) ) {
mMaxVersion = std::max( version, mMaxVersion );
fileContent += "\n"; // remove the #version but keep a newline
lineNumber++;
} else if ( lineContainsImport(line, fileToImport ) ) {
// handle import
if (fileToImport[0] != '/') {
// it's a relative path:
// remove "./" in case this was given explicitly:
if(fileToImport.size() > 2 && fileToImport[0] == '.' && fileToImport[1] == '/') {
fileToImport = fileToImport.substr(2, fileToImport.size()-2);
}
std::string path, file;
StringOperations::splitLastFileOrFolder( _filename, path, file );
fileToImport = path+"/"+fileToImport;
}
if ( std::find(mSourceFileNames.begin(), mSourceFileNames.end(), fileToImport) == mSourceFileNames.end()) {
// not imported yet:
// push what we have till now:
mSources.push_back( fileContent );
readin( fileToImport );
lineNumber++;
fileContent = "#line "+StringOperations::toString(lineNumber)+" "+StringOperations::toString(fileNumber)+"\n";
} else {
// ignore:
lineNumber++;
fileContent += "\n";
}
} else {
fileContent += line + "\n";
lineNumber++;
}
}
fileStream.close();
}
else
{
error() << "Failed to open file: " << _filename << std::endl;
return;
}
//debug() << "file: " << fileContent << std::endl;
mSources.push_back( fileContent );
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment