//! returns the base part of a filename, i.e. all except for the directory //! part. If no directory path is prefixed, the full name is returned. core::stringc CFileSystem::getFileBasename(const core::stringc& filename, bool keepExtension) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = core::max_(lastSlash, lastBackSlash); // get number of chars after last dot s32 end = 0; if (!keepExtension) { // take care to search only after last slash to check only for // dots in the filename end = filename.findLast('.', lastSlash); if (end == -1) end=0; else end = filename.size()-end; } if ((u32)lastSlash < filename.size()) return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end); else if (end != 0) return filename.subString(0, filename.size()-end); else return filename; }
bool FileSceneNode::isimg(core::stringc name) { if ((name.subString(name.size() - 4, 4).equals_ignore_case(".bmp")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".jpg")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".tga")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".pcx")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".png")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".psd"))) return true; return false; }
bool FileSceneNode::isanimesh(core::stringc name) { if ((name.subString(name.size() - 4, 4).equals_ignore_case(".md2")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".md3")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".obj")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".bsp")) || (name.subString(name.size() - 5, 5).equals_ignore_case(".my3d")) || (name.subString(name.size() - 5, 5).equals_ignore_case(".lmts")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".csm")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".oct"))) return true; return false; }
core::stringc CFileSystem::getAbsolutePath(const core::stringc& filename) const { c8 *p=0; #ifdef _IRR_WINDOWS_API_ #if !defined ( _WIN32_WCE ) c8 fpath[_MAX_PATH]; p = _fullpath( fpath, filename.c_str(), _MAX_PATH); #endif #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) c8 fpath[4096]; fpath[0]=0; p = realpath(filename.c_str(), fpath); if (!p) { // content in fpath is undefined at this point if ('0'==fpath[0]) // seems like fpath wasn't altered { // at least remove a ./ prefix if ('.'==filename[0] && '/'==filename[1]) return filename.subString(2, filename.size()-2); else return filename; } else return core::stringc(fpath); } #endif return core::stringc(p); }
core::stringc GetContextPathFromFilename( const core::stringc& filename ) { core::stringc path; s32 i=filename.size()-1; while ( i >= 0 && filename[i] != '/' ) { i--; } path = filename.subString( 0, i+1 ); return path; }
core::stringc CMS3DMeshFileLoader::stripPathFromString(const core::stringc& inString, bool returnPath) const { s32 slashIndex=inString.findLast('/'); // forward slash s32 backSlash=inString.findLast('\\'); // back slash if (backSlash>slashIndex) slashIndex=backSlash; if (slashIndex==-1)//no slashes found { if (returnPath) return core::stringc(); //no path to return else return inString; } if (returnPath) return inString.subString(0, slashIndex + 1); else return inString.subString(slashIndex+1, inString.size() - (slashIndex+1)); }
//! returns the directory part of a filename, i.e. all until the first //! slash or backslash, excluding it. If no directory path is prefixed, a '.' //! is returned. core::stringc CFileSystem::getFileDir(const core::stringc& filename) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; if ((u32)lastSlash < filename.size()) return filename.subString(0, lastSlash); else return "."; }
//! returns the base part of a filename, i.e. all except for the directory //! part. If no directory path is prefixed, the full name is returned. core::stringc CFileSystem::getFileBasename(const core::stringc& filename, bool keepExtension) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = core::max_(lastSlash, lastBackSlash); s32 end = 0; if (!keepExtension) { end = filename.findLast('.'); if (end == -1) end=0; else end = filename.size()-end; } if ((u32)lastSlash < filename.size()) return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end); else if (end != 0) return filename.subString(0, filename.size()-end); else return filename; }
bool FileSceneNode::isvid(core::stringc name) { if ((name.subString(name.size() - 4, 4).equals_ignore_case(".avi")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".wmv")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".mpg")) || (name.subString(name.size() - 5, 5).equals_ignore_case(".mpeg")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".mp4")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".mkv")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".ogm")) || (name.subString(name.size() - 3, 3).equals_ignore_case(".rm")) || (name.subString(name.size() - 5, 5).equals_ignore_case(".divx"))) return true; return false; }
core::array<SDefineExp> grabDefineExpressions(core::stringc &shaderProgram) { s32 CurrentSearchPos = 1; s32 FindHelper = 1; s32 FindHelper2 = 1; core::array<SDefineExp> DefineArray; // Dont bother stripping comments if theres no defines. if((CurrentSearchPos = shaderProgram.find("##ifdef")) == -1) return DefineArray; // Strip all comments, they get in the way. while((CurrentSearchPos = shaderProgram.find("//")) > -1) { FindHelper = shaderProgram.findNext('\n',CurrentSearchPos); if(FindHelper != -1) for(u32 i = CurrentSearchPos;i < (u32)FindHelper;++i) shaderProgram[i] = ' '; else for(u32 i = CurrentSearchPos;i < shaderProgram.size();++i) shaderProgram[i] = ' '; } while((CurrentSearchPos = shaderProgram.find("/*")) > -1) { FindHelper = shaderProgram.find("*/"); if(FindHelper > CurrentSearchPos) for(u32 i = CurrentSearchPos;i <= (u32)(FindHelper + 1);++i) shaderProgram[i] = ' '; else for(u32 i = CurrentSearchPos;i < shaderProgram.size();++i) shaderProgram[i] = ' '; } while((CurrentSearchPos = shaderProgram.find("##ifdef")) > -1) { SDefineExp DExp; DExp.IfPos = CurrentSearchPos; // Comment out the ##ifdef so that we do not find it again, and so that the compiler ignores it. shaderProgram[CurrentSearchPos] = '/'; shaderProgram[CurrentSearchPos + 1] = '/'; FindHelper = shaderProgram.findNext(' ',CurrentSearchPos); FindHelper2 = shaderProgram.findNext('\n',FindHelper); if(FindHelper == -1 || FindHelper2 == -1) { std::cerr << "Shader preprocessor encountered invalid if statement." << std::endl; return DefineArray; } // Find the appropriate expression and trim all white space. DExp.IfExp = shaderProgram.subString(FindHelper,FindHelper2 - FindHelper); DExp.IfExp.trim(); // Record if its inverse and remove ! sign from expression. if(DExp.IfExp[0] == '!') { DExp.IfExp[0] = ' '; DExp.IfExp.trim(); DExp.Inverse = true; } bool EndIfFound = false; FindHelper2 = CurrentSearchPos; s32 IfEndScope = 0; while(!EndIfFound) { FindHelper = shaderProgram.findNext('#',FindHelper2); if(FindHelper == -1 || FindHelper >= (s32)(shaderProgram.size() - 3)) { std::cerr << "Shader preprocessor encountered unmatched if statement." << std::endl; return DefineArray; } if(IfEndScope < 0) { std::cerr << "Shader preprocessor encountered unmatched endif statement." << std::endl; return DefineArray; } if(shaderProgram[FindHelper + 1] != '#') { FindHelper2 = FindHelper + 1; continue; } else if(shaderProgram[FindHelper + 2] == 'i') { IfEndScope++; } else if(shaderProgram[FindHelper + 2] == 'e' && shaderProgram[FindHelper + 3] == 'n') { if(IfEndScope == 0) break; IfEndScope--; } else if(shaderProgram[FindHelper + 2] == 'e' && shaderProgram[FindHelper + 3] == 'l') { if(IfEndScope == 0) { if(DExp.ElsePos != -1) { std::cerr << "Shader preprocessor encountered duplicate else statements per if statement." << std::endl; return DefineArray; } // Comment out the ##else so that we do not find it again, and so that the compiler ignores it. shaderProgram[FindHelper] = '/'; shaderProgram[FindHelper + 1] = '/'; DExp.ElsePos = FindHelper; } } FindHelper2 = FindHelper + 2; } // Comment out the ##endif so that we do not find it again, and so that the compiler ignores it. shaderProgram[FindHelper] = '/'; shaderProgram[FindHelper + 1] = '/'; DExp.EndPos = FindHelper; // Add the define expression to the array. DefineArray.push_back(DExp); } return DefineArray; }
//! PreProcesses a shader using Irrlicht's built-in shader preprocessor. core::stringc CShaderPreprocessor::ppShader(core::stringc shaderProgram) { core::array<SDefineExp> DefineArray = grabDefineExpressions(shaderProgram); // No need for this as its already inited at startup. //// If DefineMap is empty then initialize it. //if(DefineMap.isEmpty()) // initDefineMap(); for(u32 i = 0; i < DefineArray.size();++i) { if(DefineArray[i].IfPos == -1) break; // Either it is true and not inversed, or it is false, but inversed. // (Wish C++ had a built-in (logical) XOR operator sometimes. :P) if((DefineMap.find(DefineArray[i].IfExp) && !DefineArray[i].Inverse) || (!DefineMap.find(DefineArray[i].IfExp) && DefineArray[i].Inverse)) { if(DefineArray[i].ElsePos > -1) { // If there is an else statement then clear the else section. if(DefineArray[i].EndPos != -1) { for(int z = DefineArray[i].ElsePos;z <= DefineArray[i].EndPos + 6;++z) shaderProgram[z] = ' '; } } } else if(DefineArray[i].ElsePos != -1) { // If there is an else statement then clear the if section. for(int z = DefineArray[i].IfPos;z <= DefineArray[i].ElsePos + 5;++z) shaderProgram[z] = ' '; } else { // Else just clear the whole block. if(DefineArray[i].EndPos != -1) { for(int z = DefineArray[i].IfPos;z <= DefineArray[i].EndPos + 6;++z) shaderProgram[z] = ' '; } } } core::map<core::stringc,core::stringc>::ParentFirstIterator DefIter; s32 DefFinder = 1; // Replace all shader defines. for(DefIter = DefineMap.getParentFirstIterator();!DefIter.atEnd();DefIter++) { if(DefIter->getValue().size() == 0) continue; // Replace all occurances. while((DefFinder = shaderProgram.find(DefIter->getKey().c_str())) > -1) { // Clear the define from the code. for(u32 z = DefFinder;z < DefFinder + DefIter->getKey().size();++z) shaderProgram[z] = ' '; // Stitch value and shader program together. (Is there a faster way?) shaderProgram = shaderProgram.subString(0,DefFinder) + DefIter->getValue() + shaderProgram.subString(DefFinder,shaderProgram.size() - 1); } } return shaderProgram; }