//----------------------------------------------------------------------------- // Purpose: // Input : pszFilename - // bIndexOnly - // Output : int //----------------------------------------------------------------------------- int CPrefabLibraryRMF::Save(LPCTSTR pszFilename, BOOL bIndexOnly) { // temp storage static char szFile[MAX_PATH]; // if only saving index, special code - if(bIndexOnly && m_file.is_open()) { // close file, reopen in binary write m_file.close(); if(Prefabs.GetCount()) { // change size of file first int iHandle = _open(m_strOpenFileName, _O_BINARY | _O_WRONLY); _chsize(iHandle, m_dwDirOffset); _close(iHandle); } fstream file(m_strOpenFileName, ios::binary | ios::out); // write string header file << pLibHeader; // write binary header (in case notes have changed) PrefabLibraryHeader plh; plh.dwNumEntries = Prefabs.GetCount(); plh.fVersion = fLibVersion; plh.dwDirOffset = m_dwDirOffset; strcpy(plh.szNotes, szNotes); file.write((char*)&plh, sizeof plh); // recreate a directory and write it PrefabHeader *ph = new PrefabHeader[Prefabs.GetCount()]; int iCur = 0; POSITION p = Prefabs.GetHeadPosition(); while(p) { CPrefab *pPrefab = Prefabs.GetNext(p); // setup this dir entry ph[iCur].dwOffset = pPrefab->dwFileOffset; ph[iCur].dwSize = pPrefab->dwFileSize; strcpy(ph[iCur].szName, pPrefab->GetName()); strcpy(ph[iCur].szNotes, pPrefab->GetNotes()); ph[iCur].iType = pPrefab->GetType(); ++iCur; // increase current directory entry } // write directory file.seekp(m_dwDirOffset); file.write((char*)ph, sizeof(*ph) * Prefabs.GetCount()); file.close(); // re-open m_file.open(m_strOpenFileName, ios::in | ios::binary | ios::nocreate); return 1; } if(pszFilename == NULL) { pszFilename = szFile; if(m_strOpenFileName.IsEmpty()) { char szNewFilename[MAX_PATH]; CWorldcraft *pApp = (CWorldcraft*) AfxGetApp(); pApp->GetDirectory(DIR_PREFABS, szNewFilename); sprintf(szNewFilename + strlen(szNewFilename), "\\%s.ol", m_szName); // make a name m_strOpenFileName = szNewFilename; } strcpy(szFile, m_strOpenFileName); } else { strcpy(szFile, pszFilename); SetNameFromFilename(pszFilename); } // open temp file to save to.. then delete & rename old one. CString strTempFileName = "Temporary Prefab Library.$$$"; fstream file; file.open(strTempFileName, ios::binary | ios::out); // write string header file << pLibHeader; // write binary header // save current position so we can seek back and rewrite it DWORD dwBinaryHeaderOffset = file.tellp(); PrefabLibraryHeader plh; plh.dwNumEntries = Prefabs.GetCount(); plh.fVersion = fLibVersion; strcpy(plh.szNotes, szNotes); file.write((char*)&plh, sizeof plh); // allocate memory for directory PrefabHeader *ph = new PrefabHeader[plh.dwNumEntries]; int iCur = 0; char *pCopyBuf = new char[64000]; // write each prefab POSITION p = Prefabs.GetHeadPosition(); while (p) { CPrefabRMF *pPrefab = (CPrefabRMF *)Prefabs.GetNext(p); // setup this dir entry ph[iCur].dwOffset = file.tellp(); strcpy(ph[iCur].szName, pPrefab->GetName()); strcpy(ph[iCur].szNotes, pPrefab->GetNotes()); ph[iCur].iType = pPrefab->GetType(); if(pPrefab->IsLoaded()) { // it's loaded - save in native method pPrefab->Save(file, CPrefab::lsUpdateFilePos); } else { // it's not loaded - save with quick method by copying // bytes directly from the existing file ASSERT(m_file.is_open()); m_file.seekg(pPrefab->dwFileOffset); DWORD dwToRead = 64000, dwCopied = 0; while(dwToRead == 64000) { if(dwCopied + dwToRead > pPrefab->dwFileSize) dwToRead = pPrefab->dwFileSize - dwCopied; m_file.read(pCopyBuf, dwToRead); file.write(pCopyBuf, dwToRead); dwCopied += dwToRead; } } // set offset info HERE because we might use it above pPrefab->dwFileOffset = ph[iCur].dwOffset; // set size info ph[iCur].dwSize = pPrefab->dwFileSize = file.tellp() - ph[iCur].dwOffset; ++iCur; // increase current directory entry } // delete copy buf delete[] pCopyBuf; // rewrite binary header plh.dwDirOffset = m_dwDirOffset = file.tellp(); file.seekp(dwBinaryHeaderOffset); file.write((char*)&plh, sizeof(plh)); file.seekp(0, ios::end); // write directory file.write((char*)ph, sizeof(*ph) * plh.dwNumEntries); file.close(); // close temp file // delete original and rename m_file.close(); // might already be open.. might not. remove(m_strOpenFileName); m_strOpenFileName = szFile; int iRvl = rename(strTempFileName, m_strOpenFileName); // reopen original m_file.open(m_strOpenFileName, ios::in | ios::binary | ios::nocreate); return 1; }
void CPrefabsDlg::OnAddobject() { CPrefabLibrary *pLibrary = GetCurrentLibrary(); if(!pLibrary) return; // no lib, no add CFileDialog dlg(TRUE, NULL, NULL, OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR, "Prefab files (*.map;*.rmf;*.os)|*.map; *.rmf; *.os|" "Game MAP files (*.map)|*.map|" "Worldcraft RMF files (*.rmf)|*.rmf||", this); if(dlg.DoModal() == IDCANCEL) return; // aborted // add all these files .. char szDir[MAX_PATH], szFiles[2048]; memcpy(szFiles, dlg.m_ofn.lpstrFile, dlg.m_ofn.nMaxFile); strcpy(szDir, dlg.m_ofn.lpstrFile); BOOL bOneFile = FALSE; char *p = szFiles + strlen(szDir) + 1; if(!p[0]) { bOneFile = TRUE; p = szDir; // just one file } // disable caching of prefabs CPrefab::EnableCaching(FALSE); // get files char szFile[MAX_PATH]; CString strFullPath; int iItem = m_Objects.GetItemCount(); while(1) { strcpy(szFile, p); if(!szFile[0]) break; p += strlen(szFile) + 1; if(!bOneFile) strFullPath.Format("%s\\%s", szDir, szFile); else strFullPath = szFile; // check file type CPrefab *pPrefab = NULL; switch(CPrefab::CheckFileType(strFullPath)) { case CPrefab::pftUnknown: { continue; // no. } case CPrefab::pftRMF: { CPrefabRMF *pNew = new CPrefabRMF; pNew->Init(strFullPath, TRUE, CPrefab::lsRMF); pPrefab = (CPrefab *)pNew; break; } case CPrefab::pftMAP: { CPrefabRMF *pNew = new CPrefabRMF; pNew->Init(strFullPath, TRUE, CPrefab::lsMAP); pPrefab = (CPrefab *)pNew; break; } case CPrefab::pftScript: { Assert(0); // not supported yet break; } } if (!pPrefab) { continue; } // add to current library pLibrary->Add(pPrefab); // add to objects list AddToObjectList(pPrefab, iItem++); if(bOneFile) break; } // now rewrite library pLibrary->Sort(); pLibrary->Save(); CPrefab::FreeAllData(); // free memory // re-enable prefab caching CPrefab::EnableCaching(TRUE); bCurLibraryModified = FALSE; }
//----------------------------------------------------------------------------- // Purpose: // Input : pszFilename - // Output : int //----------------------------------------------------------------------------- int CPrefabLibraryRMF::Load(LPCTSTR pszFilename) { m_eType = LibType_HalfLife; // open file m_file.open(pszFilename, ios::in | ios::binary | ios::nocreate); m_strOpenFileName = pszFilename; if(!m_file.is_open()) return -1; char szBuf[128]; // read string header m_file.read(szBuf, strlen(pLibHeader)); if(strncmp(szBuf, pLibHeader, strlen(pLibHeader))) { // return return -1; } // read binary header PrefabLibraryHeader plh; m_file.read((char*)&plh, sizeof(plh)); strcpy(szNotes, plh.szNotes); // set name from filename SetNameFromFilename(pszFilename); // read directory PrefabHeader *ph = new PrefabHeader[plh.dwNumEntries]; m_dwDirOffset = plh.dwDirOffset; m_file.seekg(plh.dwDirOffset); m_file.read((char*)ph, plh.dwNumEntries * sizeof(PrefabHeader)); // // Read each prefab. // for(DWORD i = 0; i < plh.dwNumEntries; i++) { ASSERT(ph[i].iType == pt3D); CPrefabRMF *pPrefab = new CPrefabRMF; // seek to prefab m_file.seekg(ph[i].dwOffset); pPrefab->Init(m_file); // set its other info frm the dir entry pPrefab->SetName(ph[i].szName); pPrefab->SetNotes(ph[i].szNotes); pPrefab->dwFileSize = ph[i].dwSize; pPrefab->dwFileOffset = ph[i].dwOffset; Add(pPrefab); } // delete directory delete[] ph; return 1; }