/* Archive::importDir * Imports all files (including subdirectories) from [directory] into * the archive *******************************************************************/ bool Archive::importDir(string directory) { // Get a list of all files in the directory wxArrayString files; wxDir::GetAllFiles(directory, &files); // Go through files for (unsigned a = 0; a < files.size(); a++) { string name = files[a]; name.Replace(directory, "", false); // Remove directory from entry name // Split filename into dir+name wxFileName fn(name); string ename = fn.GetFullName(); string edir = fn.GetPath(); // Remove beginning \ or / from dir if (edir.StartsWith("\\") || edir.StartsWith("/")) edir.Remove(0, 1); // Add the entry ArchiveTreeNode* dir = createDir(edir); ArchiveEntry* entry = addNewEntry(ename, dir->numEntries()+1, dir); // Load data entry->importFile(files[a]); // Set unmodified entry->setState(0); dir->getDirEntry()->setState(0); } return true; }
/* TextureXPanel::newTextureFromFile * Creates a new texture from an image file. The file will be * imported and added to the patch table if needed *******************************************************************/ void TextureXPanel::newTextureFromFile() { // Get all entry types vector<EntryType*> etypes = EntryType::allTypes(); // Go through types string ext_filter = "All files (*.*)|*.*|"; for (unsigned a = 0; a < etypes.size(); a++) { // If the type is a valid image type, add its extension filter if (etypes[a]->extraProps().propertyExists("image")) { ext_filter += etypes[a]->getFileFilterString(); ext_filter += "|"; } } // Create open file dialog wxFileDialog dialog_open(this, "Choose file(s) to open", dir_last, wxEmptyString, ext_filter, wxFD_OPEN|wxFD_MULTIPLE|wxFD_FILE_MUST_EXIST, wxDefaultPosition); // Run the dialog & check that the user didn't cancel if (dialog_open.ShowModal() == wxID_OK) { // Get file selection wxArrayString files; dialog_open.GetPaths(files); // Save 'dir_last' dir_last = dialog_open.GetDirectory(); // Go through file selection for (unsigned a = 0; a < files.size(); a++) { // Load the file into a temporary ArchiveEntry ArchiveEntry* entry = new ArchiveEntry(); entry->importFile(files[a]); // Determine type EntryType::detectEntryType(entry); // If it's not a valid image type, ignore this file if (!entry->getType()->extraProps().propertyExists("image")) { wxLogMessage("%s is not a valid image file", files[a]); continue; } // Ask for name for texture wxFileName fn(files[a]); string name = fn.GetName().Upper().Truncate(8); name = wxGetTextFromUser(S_FMT("Enter a texture name for %s:", fn.GetFullName()), "New Texture", name); name = name.Truncate(8); // Add patch to archive entry->setName(name); entry->setExtensionByType(); tx_entry->getParent()->addEntry(entry, "patches"); // Add patch to patch table if needed if (texturex.getFormat() != TXF_TEXTURES) tx_editor->patchTable().addPatch(name); // Create new texture from patch CTexture* tex = newTextureFromPatch(name, name); // Add texture after the last selected item int selected = list_textures->getLastSelected(); if (selected == -1) selected = texturex.nTextures() - 1; // Add to end of the list if nothing selected texturex.addTexture(tex, selected + 1); // Record undo level undo_manager->beginRecord("New Texture from File"); undo_manager->recordUndoStep(new TextureCreateDeleteUS(this, tex, true)); undo_manager->endRecord(true); // Update texture list list_textures->updateList(); // Select the new texture list_textures->clearSelection(); list_textures->selectItem(selected + 1); list_textures->EnsureVisible(selected + 1); // Update patch table counts tx_editor->patchTable().updatePatchUsage(tex); } } }
/* PatchTablePanel::onBtnPatchFromFile * Called when the 'New Patch from File' button is clicked *******************************************************************/ void PatchTablePanel::onBtnPatchFromFile(wxCommandEvent& e) { // Get all entry types vector<EntryType*> etypes = EntryType::allTypes(); // Go through types string ext_filter = "All files (*.*)|*.*|"; for (unsigned a = 0; a < etypes.size(); a++) { // If the type is a valid image type, add its extension filter if (etypes[a]->extraProps().propertyExists("image")) { ext_filter += etypes[a]->getFileFilterString(); ext_filter += "|"; } } // Create open file dialog wxFileDialog dialog_open(this, "Choose file(s) to open", dir_last, wxEmptyString, ext_filter, wxFD_OPEN|wxFD_MULTIPLE|wxFD_FILE_MUST_EXIST, wxDefaultPosition); // Run the dialog & check that the user didn't cancel if (dialog_open.ShowModal() == wxID_OK) { // Get file selection wxArrayString files; dialog_open.GetPaths(files); // Save 'dir_last' dir_last = dialog_open.GetDirectory(); // Go through file selection for (unsigned a = 0; a < files.size(); a++) { // Load the file into a temporary ArchiveEntry ArchiveEntry* entry = new ArchiveEntry(); entry->importFile(files[a]); // Determine type EntryType::detectEntryType(entry); // If it's not a valid image type, ignore this file if (!entry->getType()->extraProps().propertyExists("image")) { wxLogMessage("%s is not a valid image file", files[a]); continue; } // Ask for name for patch wxFileName fn(files[a]); string name = fn.GetName().Upper().Truncate(8); name = wxGetTextFromUser(S_FMT("Enter a patch name for %s:", fn.GetFullName()), "New Patch", name); name = name.Truncate(8); // Add patch to archive entry->setName(name); entry->setExtensionByType(); parent->getArchive()->addEntry(entry, "patches"); // Add patch to patch table patch_table->addPatch(name); } // Refresh patch list list_patches->updateList(); parent->pnamesModified(true); } }
/* EntryOperations::compileACS * Attempts to compile [entry] as an ACS script. If the entry is * named SCRIPTS, the compiled data is imported to the BEHAVIOR * entry previous to it, otherwise it is imported to a same-name * compiled library entry in the acs namespace *******************************************************************/ bool EntryOperations::compileACS(ArchiveEntry* entry, bool hexen, ArchiveEntry* target, wxFrame* parent) { // Check entry was given if (!entry) return false; // Check entry has a parent (this is useless otherwise) if (!target && !entry->getParent()) return false; // Check entry is text if (!EntryDataFormat::getFormat("text")->isThisFormat(entry->getMCData())) { wxMessageBox("Error: Entry does not appear to be text", "Error", wxOK|wxCENTRE|wxICON_ERROR); return false; } // Check if the ACC path is set up string accpath = path_acc; if (accpath.IsEmpty() || !wxFileExists(accpath)) { wxMessageBox("Error: ACC path not defined, please configure in SLADE preferences", "Error", wxOK|wxCENTRE|wxICON_ERROR); PreferencesDialog::openPreferences(parent, "ACS"); return false; } // Setup some path strings string srcfile = appPath(entry->getName(true) + ".acs", DIR_TEMP); string ofile = appPath(entry->getName(true) + ".o", DIR_TEMP); wxArrayString include_paths = wxSplit(path_acc_libs, ';'); // Setup command options string opt; if (hexen) opt += " -h"; if (!include_paths.IsEmpty()) { for (unsigned a = 0; a < include_paths.size(); a++) opt += S_FMT(" -i \"%s\"", include_paths[a]); } // Find/export any resource libraries Archive::search_options_t sopt; sopt.match_type = EntryType::getType("acs"); sopt.search_subdirs = true; vector<ArchiveEntry*> entries = theArchiveManager->findAllResourceEntries(sopt); wxArrayString lib_paths; for (unsigned a = 0; a < entries.size(); a++) { // Ignore SCRIPTS if (S_CMPNOCASE(entries[a]->getName(true), "SCRIPTS")) continue; // Ignore entries from other archives if (entry->getParent() && (entry->getParent()->getFilename(true) != entries[a]->getParent()->getFilename(true))) continue; string path = appPath(entries[a]->getName(true) + ".acs", DIR_TEMP); entries[a]->exportFile(path); lib_paths.Add(path); LOG_MESSAGE(2, "Exporting ACS library %s", entries[a]->getName()); } // Export script to file entry->exportFile(srcfile); // Execute acc string command = path_acc + " " + opt + " \"" + srcfile + "\" \"" + ofile + "\""; wxArrayString output; wxArrayString errout; theApp->SetTopWindow(parent); wxExecute(command, output, errout, wxEXEC_SYNC); theApp->SetTopWindow(theMainWindow); // Log output theConsole->logMessage("ACS compiler output:"); string output_log; if (!output.IsEmpty()) { const char *title1 = "=== Log: ===\n"; theConsole->logMessage(title1); output_log += title1; for (unsigned a = 0; a < output.size(); a++) { theConsole->logMessage(output[a]); output_log += output[a]; } } if (!errout.IsEmpty()) { const char *title2 = "\n=== Error log: ===\n"; theConsole->logMessage(title2); output_log += title2; for (unsigned a = 0; a < errout.size(); a++) { theConsole->logMessage(errout[a]); output_log += errout[a]; } } // Delete source file wxRemoveFile(srcfile); // Delete library files for (unsigned a = 0; a < lib_paths.size(); a++) wxRemoveFile(lib_paths[a]); // Check it compiled successfully if (wxFileExists(ofile)) { // If no target entry was given, find one if (!target) { // Check if the script is a map script (BEHAVIOR) if (S_CMPNOCASE(entry->getName(), "SCRIPTS")) { // Get entry before SCRIPTS ArchiveEntry* prev = entry->prevEntry(); // Create a new entry there if it isn't BEHAVIOR if (!prev || !(S_CMPNOCASE(prev->getName(), "BEHAVIOR"))) prev = entry->getParent()->addNewEntry("BEHAVIOR", entry->getParent()->entryIndex(entry)); // Import compiled script prev->importFile(ofile); } else { // Otherwise, treat it as a library // See if the compiled library already exists as an entry Archive::search_options_t opt; opt.match_namespace = "acs"; opt.match_name = entry->getName(true); if (entry->getParent()->getDesc().names_extensions) { opt.match_name += ".o"; opt.ignore_ext = false; } ArchiveEntry* lib = entry->getParent()->findLast(opt); // If it doesn't exist, create it if (!lib) lib = entry->getParent()->addEntry(new ArchiveEntry(entry->getName(true) + ".o"), "acs"); // Import compiled script lib->importFile(ofile); } } else target->importFile(ofile); // Delete compiled script file wxRemoveFile(ofile); } else { string errors; if (wxFileExists(appPath("acs.err", DIR_TEMP))) { // Read acs.err to string wxFile file(appPath("acs.err", DIR_TEMP)); char* buf = new char[file.Length()]; file.Read(buf, file.Length()); errors = wxString::From8BitData(buf, file.Length()); delete[] buf; } else errors = output_log; ExtMessageDialog dlg(NULL, "Error Compiling"); dlg.setMessage("The following errors were encountered while compiling, please fix them and recompile:"); dlg.setExt(errors); dlg.ShowModal(); return false; } return true; }
/* DirArchive::updateChangedEntries * Updates entries/directories based on [changes] list *******************************************************************/ void DirArchive::updateChangedEntries(vector<dir_entry_change_t>& changes) { bool was_modified = isModified(); for (unsigned a = 0; a < changes.size(); a++) { ignored_file_changes.erase(changes[a].file_path); // Modified Entries if (changes[a].action == dir_entry_change_t::UPDATED) { ArchiveEntry* entry = entryAtPath(changes[a].entry_path); entry->importFile(changes[a].file_path); EntryType::detectEntryType(entry); file_modification_times[entry] = wxFileModificationTime(changes[a].file_path); } // Deleted Entries else if (changes[a].action == dir_entry_change_t::DELETED_FILE) removeEntry(entryAtPath(changes[a].entry_path)); // Deleted Directories else if (changes[a].action == dir_entry_change_t::DELETED_DIR) removeDir(changes[a].entry_path); // New Directory else if (changes[a].action == dir_entry_change_t::ADDED_DIR) { string name = changes[a].file_path; name.Remove(0, filename.Length()); if (name.StartsWith(separator)) name.Remove(0, 1); name.Replace("\\", "/"); ArchiveTreeNode* ndir = createDir(name); ndir->getDirEntry()->setState(0); ndir->getDirEntry()->exProp("filePath") = changes[a].file_path; } // New Entry else if (changes[a].action == dir_entry_change_t::ADDED_FILE) { string name = changes[a].file_path; name.Remove(0, filename.Length()); if (name.StartsWith(separator)) name.Remove(0, 1); name.Replace("\\", "/"); // Create entry wxFileName fn(name); ArchiveEntry* new_entry = new ArchiveEntry(fn.GetFullName()); // Setup entry info new_entry->setLoaded(false); new_entry->exProp("filePath") = changes[a].file_path; // Add entry and directory to directory tree ArchiveTreeNode* ndir = createDir(fn.GetPath(true, wxPATH_UNIX)); ndir->addEntry(new_entry); // Read entry data new_entry->importFile(changes[a].file_path); new_entry->setLoaded(true); time_t modtime = wxFileModificationTime(changes[a].file_path); file_modification_times[new_entry] = modtime; // Detect entry type EntryType::detectEntryType(new_entry); // Unload data if needed if (!archive_load_data) new_entry->unloadData(); // Set entry not modified new_entry->setState(0); } } // Preserve old modified state setModified(was_modified); }