//Filename:- oldskins.cpp // // module containing code for old ID/EF1/CHC style skins... // #include "stdafx.h" #include "includes.h" #include "files.h" #include "r_common.h" //#include "ModViewTreeView.h" //#include "glm_code.h" //#include "R_Model.h" //#include "R_Surface.h" #include "textures.h" //#include "TEXT.H" //#include "sequence.h" //#include "model.h" ////#include "GenericParser.h" #include "oldskins.h" // file format: (dead simple) // //armor_chest,models/players/stormtrooper/torso_legs.tga //armor_neck_augment,models/players/stormtrooper/torso_legs.tga //body_torso,models/players/stormtrooper/torso_legs.tga OldSkinSets_t OldSkinsFound; // returns NULL for all ok, else error string... // LPCSTR OldSkins_Parse(LPCSTR psSkinName, LPCSTR psText) { CString strText(psText); strText.Replace(va("%c%c",0x0A,0x0D),va("%c",0x0A)); // file was read in binary mode, so account for 0x0A/0x0D pairs strText.Replace("\t",""); strText.Replace(" ",""); strText.MakeLower(); while (!strText.IsEmpty()) { CString strThisLine; int iLoc = strText.Find('\n'); if (iLoc == -1) { strThisLine = strText; strText.Empty(); } else { strThisLine = strText.Left(iLoc); strText = strText.Mid(iLoc+1); } if (!strThisLine.IsEmpty()) { iLoc = strThisLine.Find(','); if (iLoc != -1) { CString strSurfaceName (strThisLine.Left(iLoc)); CString strTGAName (strThisLine.Mid (iLoc+1)); strSurfaceName.TrimLeft(); strSurfaceName.TrimRight(); strTGAName.TrimLeft(); strTGAName.TrimRight(); // // new bit to cope with faulty ID skin files, where they have spurious lines like "tag_torso," // // ("tag" is "*" in ghoul2) // if (strSurfaceName.GetAt(0) == '*' || strTGAName.IsEmpty()) { // crap line, so ignore it... } else { OldSkinsFound[psSkinName].push_back(StringPairVector_t::value_type((LPCSTR)strSurfaceName,(LPCSTR)strTGAName)); } } else { return va("Error parsing line \"%s\" in skin \"%s\"!",(LPCSTR)strThisLine,psSkinName); } } } return NULL; } // converts stuff like "/stormtrooper_blue.skin" to "blue"... // LPCSTR OldSkins_FilenameToSkinDescription(string strLocalSkinFileName) { static char sTemp[1024]; CString strSkinName(Filename_WithoutPath(Filename_WithoutExt(strLocalSkinFileName.c_str()))); strSkinName.MakeLower(); int iLoc = strSkinName.Find('_'); if (iLoc != -1) { strSkinName = strSkinName.Mid(iLoc+1); } sprintf(sTemp,strSkinName); return sTemp; } // returns true if at least one set of skin data was read, else false... // static bool OldSkins_Read(LPCSTR psLocalFilename_GLM) { LPCSTR psError = NULL; CWaitCursor; OldSkinsFound.clear(); LPCSTR psSkinsPath = va("%s%s",gamedir,Filename_PathOnly(psLocalFilename_GLM)); if (psSkinsPath) { CString strSkinFileMustContainThisName( Filename_WithoutPath( Filename_WithoutExt( psLocalFilename_GLM )) ); strSkinFileMustContainThisName += "_"; // eg: "turret_canon_" char **ppsSkinFiles; int iSkinFiles; // scan for skin files... // ppsSkinFiles = //ri.FS_ListFiles( "shaders", ".shader", &iSkinFiles ); Sys_ListFiles( psSkinsPath,// const char *directory, ".skin", // const char *extension, NULL, // char *filter, &iSkinFiles,// int *numfiles, qfalse // qboolean wantsubs ); if ( !ppsSkinFiles || !iSkinFiles ) { return false; } if ( iSkinFiles > MAX_SKIN_FILES ) { WarningBox(va("%d skin files found, capping to %d\n\n(tell me if this ever happens -Ste)", iSkinFiles, MAX_SKIN_FILES )); iSkinFiles = MAX_SKIN_FILES; } // load and parse skin files... // char *buffers[MAX_SKIN_FILES] = {0}; long iTotalBytesLoaded = 0; for ( int i=0; iOldSkinSets = OldSkinsFound; // huge nested stl-copy /* for (OldSkinSets_t::iterator it = OldSkinsFound.begin(); it != OldSkinsFound.end(); ++it) { string strFile = (*it).first; StringPairVector_t &blah = (*it).second; for (StringPairVector_t::iterator it2 = blah.begin(); it2 != blah.end(); ++it2) { string str1 = (*it2).first; string str2 = (*it2).second; OutputDebugString(va("Skin %s: %s, %s\n",strFile.c_str(),str1.c_str(),str2.c_str())); OutputDebugString(__DATE__); OutputDebugString("\n"); } } */ return true; } return false; } // psSkinName = "blue", or "default" etc... // // this fills in a modelcontainer's "MaterialBinds" and "MaterialShaders" fields (registering textures etc) // based on the skinset pointed at by pContainer->OldSkinSets and strSkinFile // bool OldSkins_Apply( ModelContainer_t *pContainer, LPCSTR psSkinName ) { CWaitCursor wait; bool bReturn = true; pContainer->strCurrentSkinFile = psSkinName; // pContainer->strCurrentSkinEthnic= ""; pContainer->MaterialBinds.clear(); pContainer->MaterialShaders.clear(); for (int iSurface = 0; iSurfaceiNumSurfaces; iSurface++) { // when we're at this point we know it's GLM model, and that the shader name is in fact a material name... // LPCSTR psMaterialName = GLMModel_GetSurfaceShaderName( pContainer->hModel, iSurface ); pContainer->MaterialShaders [psMaterialName] = ""; // just insert the key for now, so the map<> is legit. pContainer->MaterialBinds [psMaterialName] = (GLuint) 0; // default to gl-white-notfound texture } //typedef vector< pair > StringPairVector_t; //typedef map OldSkinSets_t; // map key = (eg) "blue", string-pairs OldSkinSets_t::iterator itOldSkins = pContainer->OldSkinSets.find(psSkinName); if (itOldSkins != pContainer->OldSkinSets.end()) { StringPairVector_t &StringPairs = (*itOldSkins).second; for (int iSkinEntry = 0; iSkinEntry < StringPairs.size(); iSkinEntry++) { LPCSTR psMaterialName = StringPairs[iSkinEntry].first.c_str(); LPCSTR psShaderName = StringPairs[iSkinEntry].second.c_str(); pContainer->MaterialShaders[psMaterialName] = psShaderName; // LPCSTR psLocalTexturePath = R_FindShader( psShaderName ); // shader->texture name // if (psLocalTexturePath && strlen(psLocalTexturePath)) // { // TextureHandle_t hTexture = TextureHandle_ForName( psLocalTexturePath ); // // if (hTexture == -1) // { // hTexture = Texture_Load(psLocalTexturePath); // } // // GLuint uiBind = Texture_GetGLBind( hTexture ); // // pContainer->MaterialBinds[psMaterialName] = uiBind; // } TextureHandle_t hTexture = Texture_Load(psShaderName); GLuint uiBind = Texture_GetGLBind( hTexture ); pContainer->MaterialBinds[psMaterialName] = uiBind; } } return bReturn; } bool OldSkins_ApplyToTree(HTREEITEM hTreeItem_Parent, ModelContainer_t *pContainer) { bool bReturn = false; if (pContainer->OldSkinSets.size()) { bReturn = true; TreeItemData_t TreeItemData={0}; TreeItemData.iItemType = TREEITEMTYPE_OLDSKINSHEADER; TreeItemData.iModelHandle = pContainer->hModel; HTREEITEM hTreeItem_SkinsHeader = ModelTree_InsertItem("Skins available", hTreeItem_Parent, TreeItemData.uiData); // skins... // int iSkinNumber = 0; for (OldSkinSets_t::iterator itSkins = pContainer->OldSkinSets.begin(); itSkins != pContainer->OldSkinSets.end(); ++itSkins, iSkinNumber++) { string strSkinName((*itSkins).first); // eg "blue" TreeItemData.iItemNumber = iSkinNumber; TreeItemData.iItemType = TREEITEMTYPE_OLDSKIN; HTREEITEM hTreeItem_ThisSkin = ModelTree_InsertItem(strSkinName.c_str(), hTreeItem_SkinsHeader, TreeItemData.uiData); /* // body parts... // StringPairVector_t &StringPairs = (*itSkins).second); int iMaterialNumber = 0; for (StringPairVector_t::iterator itMaterial = StringPairs.begin(); itMaterial != StringPairs.end(); ++itMaterial, iMaterialNumber++) { string strMaterialName((*itMaterial).first); // eg "face" string strShaderName ((*itMaterial).second); // eg "face" TreeItemData.iItemNumber = iMaterialNumber; TreeItemData.iItemType = TREEITEMTYPE_SKINMATERIAL; HTREEITEM hTreeItem_ThisMaterial = ModelTree_InsertItem(strMaterialName.c_str(), hTreeItem_ThisEthnic, TreeItemData.uiData); // available shader variants for this material... // for (int iShaderVariantIndex=0; iShaderVariantIndex<(*itMaterial).second.size(); iShaderVariantIndex++) { string strShaderVariantName((*itMaterial).second[iShaderVariantIndex]); // eg "models/characters/average_sleeves/face" TreeItemData.iItemNumber = iShaderVariantIndex; TreeItemData.iItemType = TREEITEMTYPE_SKINMATERIALSHADER; HTREEITEM hTreeItem_ThisShaderVariant = ModelTree_InsertItem(strShaderVariantName.c_str(), hTreeItem_ThisMaterial, TreeItemData.uiData); } } */ } } return bReturn; } // sets up valid skin tables based on first entries loaded, also registers/binds appropriate textures... // void OldSkins_ApplyDefault(ModelContainer_t *pContainer) { string strCurrentSkin; // look for one called "default" first... // OldSkinSets_t::iterator itSkins = pContainer->OldSkinSets.find("default"); if (itSkins != pContainer->OldSkinSets.end()) { strCurrentSkin = (*itSkins).first; } else { // just use the first one we have... // for (itSkins = pContainer->OldSkinSets.begin(); itSkins != pContainer->OldSkinSets.end();) { strCurrentSkin = (*itSkins).first; break; } } // apply it, but don't barf if there wasn't one... // if (!strCurrentSkin.empty()) { OldSkins_Apply(pContainer, strCurrentSkin.c_str()); } } GLuint OldSkins_GetGLBind(ModelContainer_t *pContainer, LPCSTR psSurfaceName) { /* debug only, do NOT leave in or massive performance hit!! int iSize = pContainer->MaterialBinds.size(); for (MaterialBinds_t::iterator it = pContainer->MaterialBinds.begin(); it != pContainer->MaterialBinds.end(); ++it) { string str = (*it).first; GLuint gl = (*it).second; OutputDebugString(va("%s (%d)\n",str.c_str(), gl)); } */ return pContainer->MaterialBinds[psSurfaceName]; } extern bool g_bReportImageLoadErrors; bool OldSkins_Validate( ModelContainer_t *pContainer, int iSkinNumber ) { bool bReturn = true; bool bPREV_bReportImageLoadErrors = g_bReportImageLoadErrors; g_bReportImageLoadErrors = false; // build up a list of shaders used... // StringSet_t UniqueSkinShaders; //SkinFileMaterialsMissing_t SkinFileMaterialsMissing; int iThisSkinIndex = 0; CString strSkinFileSurfaceDiscrepancies; for (OldSkinSets_t::iterator itOldSkins = pContainer->OldSkinSets.begin(); itOldSkins != pContainer->OldSkinSets.end(); ++itOldSkins, iThisSkinIndex++) { string strSkinName = (*itOldSkins).first; StringPairVector_t &StringPairs = (*itOldSkins).second; if (iSkinNumber == iThisSkinIndex || iSkinNumber == -1) { for (int iSurface = 0; iSurface < StringPairs.size(); iSurface++) { string strSurface(StringPairs[iSurface].first); string strTGAName(StringPairs[iSurface].second); UniqueSkinShaders.insert(UniqueSkinShaders.end(),strTGAName); if (iSkinNumber == -1) { // compare the current material against every other skin file, and report any that don't contain it... // for (OldSkinSets_t::iterator itOldSkins_Other = pContainer->OldSkinSets.begin(); itOldSkins_Other != pContainer->OldSkinSets.end(); ++itOldSkins_Other) { string strSkinName_Other = (*itOldSkins_Other).first; StringPairVector_t &StringPairs_Other = (*itOldSkins_Other).second; for (int iSurface_Other = 0; iSurface_Other < StringPairs_Other.size(); iSurface_Other++) { string strSurface_Other(StringPairs_Other[iSurface_Other].first); if (strSurface_Other == strSurface) { break; } } if (iSurface_Other == StringPairs_Other.size()) { // surface not found in this file... // strSkinFileSurfaceDiscrepancies += va("Surface \"%s\" ( skin \"%s\" ) had no entry in skin \"%s\"\n",strSurface.c_str(),strSkinName.c_str(),strSkinName_Other.c_str()); } } } } } } // now process the unique list we've just built... // CWaitCursor wait; string strFoundList; string strNotFoundList; int iUniqueIndex = 0; for (StringSet_t::iterator it = UniqueSkinShaders.begin(); it != UniqueSkinShaders.end(); ++it, iUniqueIndex++) { string strShader(*it); StatusMessage(va("Processing shader %d/%d: \"%s\"\n",iUniqueIndex,UniqueSkinShaders.size(),strShader.c_str())); OutputDebugString(va("Unique: \"%s\"... ",strShader.c_str())); int iTextureHandle = Texture_Load(strShader.c_str(), true); // bInhibitStatus GLuint uiGLBind = Texture_GetGLBind( iTextureHandle ); if (uiGLBind == 0) { OutputDebugString("NOT FOUND\n"); strNotFoundList += strShader; strNotFoundList += "\n"; } else { OutputDebugString("found\n"); strFoundList += strShader; strFoundList += "\n"; } } StatusMessage(NULL); // Now output results... // If too many lines to fit on screen (which is now happening), send 'em to notepad instead... // // ( tacky way of counting lines...) CString strTackyCount(strNotFoundList.c_str()); strTackyCount += strFoundList.c_str(); int iLines = strTackyCount.Replace('\n','?'); // :-) #define MAX_BOX_LINES_HERE 50 // new popup before the other ones... // if (!strSkinFileSurfaceDiscrepancies.IsEmpty()) { strSkinFileSurfaceDiscrepancies.Insert(0,va("( \"%s\" )\n\nThe following skin file errors occured during cross-checking...\n\n",pContainer->sLocalPathName)); if (GetYesNo(va("%s\n\nSend copy of report to Notepad?", (LPCSTR) strSkinFileSurfaceDiscrepancies))) { SendStringToNotepad( strSkinFileSurfaceDiscrepancies, "skinfile_discrepancies.txt"); } } if (strNotFoundList.empty()) { if (iLines > MAX_BOX_LINES_HERE) { if (GetYesNo(va("All shaders found... :-)\n\nList has > %d entries, send to Notepad?",MAX_BOX_LINES_HERE))) { SendStringToNotepad(va("All shaders found... :-)\n\nList follows:\n\n%s",strFoundList.c_str()),"found_shaders.txt"); } } else { InfoBox(va("All shaders found... :-)\n\nList follows:\n\n%s",strFoundList.c_str())); } } else { if (iLines > MAX_BOX_LINES_HERE) { if (GetYesNo(va("Some missing shader, some found, but list is > %d entries, send to Notepad?",MAX_BOX_LINES_HERE))) { SendStringToNotepad(va("Missing shaders:\n\n%s\n\nFound shaders:\n\n%s",strNotFoundList.c_str(),strFoundList.c_str()),"found_shaders.txt"); } } else { WarningBox(va("Missing shaders:\n\n%s\n\nFound shaders:\n\n%s",strNotFoundList.c_str(),strFoundList.c_str())); } bReturn = false; } g_bReportImageLoadErrors = bPREV_bReportImageLoadErrors; return bReturn; } /* #include "sys/timeb.h" typedef struct { char *psName; int iDays; } MonthInfo_t; MonthInfo_t Months[]= { // {"January", 31}, // {"February", 28}, // fuck the leap years // {"March", 31}, // {"April", 30}, // {"May", 31}, // {"June", 30}, // {"July", 31}, // {"August", 31}, // {"September", 30}, // {"October", 31}, // {"November", 30}, // {"December", 31} {"Jan", 31}, {"Feb", 28}, {"Mar", 31}, {"Apr", 30}, {"May", 31}, {"Jun", 30}, {"Jul", 31}, {"Aug", 31}, {"Sep", 30}, {"Oct", 31}, {"Nov", 30}, {"Dec", 31} }; char sCompileDate[] = {__DATE__}; // returns # days since compile. // // If return is -ve, then someone's messing with their machine time, or there's an error working it out, so // make your own mind up what to do. // int DaysSinceCompile(void) { int iCompileDay = 0; int iThisDay = 0; for (int iPass=0; iPass<2; iPass++) { char sTestDate[1024]; char _month[1024]; int _day,_year; if (!iPass){ strcpy(sTestDate,sCompileDate); } else { time_t ltime; _tzset(); time( <ime ); struct tm *today = localtime(<ime); strftime(sTestDate,sizeof(sTestDate),"%b %d %Y",today); } sscanf(sTestDate,"%s %d %d",&_month,&_day,&_year); int iDay = 0; for (int i=0; i<12; i++) { if (!strnicmp(_month,Months[i].psName,strlen(Months[i].psName))) break; iDay += Months[i].iDays; } if (i==12) { // ERROR: couldn't determine month // return -1; } iDay += _day; iDay += _year*365; if (!iPass){ iCompileDay = iDay; } else { iThisDay = iDay; } } return iThisDay - iCompileDay; } */ ////////////////// eof /////////////////