// ---------------------------------------------------------------------------- // ArchiveEntryList::labelEdited // // Called when a label has been edited // ---------------------------------------------------------------------------- void ArchiveEntryList::labelEdited(int col, int index, string new_label) { if (undo_manager) undo_manager->beginRecord("Rename Entry"); // Rename the entry ArchiveEntry* entry = getEntry(index); if (entry->getParent()) entry->getParent()->renameEntry(entry, new_label); else entry->rename(new_label); if (undo_manager) undo_manager->endRecord(true); }
/* PatchTableListView::getItemText * Returns the string for [item] at [column] *******************************************************************/ string PatchTableListView::getItemText(long item, long column, long index) const { // Check patch table exists if (!patch_table) return "INVALID INDEX"; // Check index is ok if (index < 0 || (unsigned)index > patch_table->nPatches()) return "INVALID INDEX"; // Get associated patch patch_t& patch = patch_table->patch(index); if (column == 0) // Index column return S_FMT("%04d", index); else if (column == 1) // Name column return patch.name; else if (column == 2) // Usage count column return S_FMT("%lu", patch.used_in.size()); else if (column == 3) // Archive column { // Get patch entry ArchiveEntry* entry = patch_table->patchEntry(index); // If patch entry can't be found return invalid if (entry) return entry->getParent()->getFilename(false); else return "(!) NOT FOUND"; } else // Invalid column return "INVALID COLUMN"; }
/* TextureXPanel::paste * Pastes any textures on the clipboard after the last selected * texture *******************************************************************/ void TextureXPanel::paste() { // Check there is anything on the clipboard if (theClipboard->nItems() == 0) return; // Get last selected index int selected = list_textures->getLastSelected(); if (selected == -1) selected = texturex.nTextures() - 1; // Add to end of the list if nothing selected // Begin recording undo level undo_manager->beginRecord("Paste Texture(s)"); // Go through clipboard items for (unsigned a = 0; a < theClipboard->nItems(); a++) { // Skip if not a texture clipboard item if (theClipboard->getItem(a)->getType() != CLIPBOARD_COMPOSITE_TEXTURE) continue; // Get texture item TextureClipboardItem* item = (TextureClipboardItem*)(theClipboard->getItem(a)); // Add new texture after last selected item CTexture* ntex = new CTexture((texturex.getFormat() == TXF_TEXTURES)); ntex->copyTexture(item->getTexture(), true); ntex->setState(2); texturex.addTexture(ntex, ++selected); // Record undo step undo_manager->recordUndoStep(new TextureCreateDeleteUS(this, ntex, true)); // Deal with patches for (unsigned p = 0; p < ntex->nPatches(); p++) { CTPatch* patch = ntex->getPatch(p); // Update patch table if necessary if (texturex.getFormat() != TXF_TEXTURES) tx_editor->patchTable().addPatch(patch->getName()); // Get the entry for this patch ArchiveEntry* entry = patch->getPatchEntry(tx_editor->getArchive()); // If the entry wasn't found in any open archive, try copying it from the clipboard // (the user may have closed the archive the original patch was in) if (!entry) { entry = item->getPatchEntry(patch->getName()); // Copy the copied patch entry over to this archive if (entry) tx_editor->getArchive()->addEntry(entry, "patches", true); } // If the entry exists in the base resource archive or this archive, do nothing else if (entry->getParent() == theArchiveManager->baseResourceArchive() || entry->getParent() == tx_editor->getArchive()) continue; // Otherwise, copy the entry over to this archive else tx_editor->getArchive()->addEntry(entry, "patches", true); } } // End recording undo level undo_manager->endRecord(true); // Refresh list_textures->updateList(); // Update variables modified = true; }
/* PatchTablePanel::updateDisplay * Called when a different patch or palette is selected * TODO: Separate palette changed and patch changed without breaking * default palette display; optimize label_textures display *******************************************************************/ void PatchTablePanel::updateDisplay() { // Get selected patch patch_t& patch = patch_table->patch(list_patches->getLastSelected()); // Load the image ArchiveEntry* entry = patch_table->patchEntry(list_patches->getLastSelected()); if (Misc::loadImageFromEntry(patch_canvas->getImage(), entry)) { theMainWindow->getPaletteChooser()->setGlobalFromArchive(entry->getParent()); patch_canvas->setPalette(theMainWindow->getPaletteChooser()->getSelectedPalette()); label_dimensions->SetLabel(S_FMT("Size: %d x %d", patch_canvas->getImage()->getWidth(), patch_canvas->getImage()->getHeight())); } else { patch_canvas->getImage()->clear(); label_dimensions->SetLabel("Size: ? x ?"); } patch_canvas->Refresh(); // List which textures use this patch if (patch.used_in.size() > 0) { string alltextures = ""; int count = 0; string previous = ""; for (size_t a = 0; a < patch.used_in.size(); ++a) { string current = patch.used_in[a]; // Is the use repeated for the same texture? if (!current.CmpNoCase(previous)) { count++; // Else it's a new texture } else { // First add the count to the previous texture if needed if (count) { alltextures += S_FMT(" (%i)", count + 1); count = 0; } // Add a separator if appropriate if (a > 0) alltextures += ';'; // Then print the new texture's name alltextures += S_FMT(" %s", patch.used_in[a].mb_str()); // And set it for comparison with the next one previous = current; } } // If count is still non-zero, it's because the patch was repeated in the last texture if (count) alltextures += S_FMT(" (%i)", count + 1); // Finally display the listing label_textures->SetLabel(S_FMT("In Textures:%s", alltextures.mb_str())); } else label_textures->SetLabel("In Textures: -"); // Wrap the text label label_textures->Wrap(label_textures->GetSize().GetWidth()); // Update layout Layout(); }
// ----------------------------------------------------------------------------- // Removes any patches and associated entries from [archive] that are not used // in any texture definitions // ----------------------------------------------------------------------------- bool ArchiveOperations::removeUnusedPatches(Archive* archive) { if (!archive) return false; // Find PNAMES entry Archive::SearchOptions opt; opt.match_type = EntryType::fromId("pnames"); ArchiveEntry* pnames = archive->findLast(opt); // Find TEXTUREx entries opt.match_type = EntryType::fromId("texturex"); vector<ArchiveEntry*> tx_entries = archive->findAll(opt); // Can't do anything without PNAMES/TEXTUREx if (!pnames || tx_entries.size() == 0) return false; // Open patch table PatchTable ptable; ptable.loadPNAMES(pnames, archive); // Open texturex entries to update patch usage vector<TextureXList*> tx_lists; for (unsigned a = 0; a < tx_entries.size(); a++) { TextureXList* texturex = new TextureXList(); texturex->readTEXTUREXData(tx_entries[a], ptable); for (unsigned t = 0; t < texturex->nTextures(); t++) ptable.updatePatchUsage(texturex->getTexture(t)); tx_lists.push_back(texturex); } // Go through patch table unsigned removed = 0; vector<ArchiveEntry*> to_remove; for (unsigned a = 0; a < ptable.nPatches(); a++) { auto& p = ptable.patch(a); // Check if used in any texture if (p.used_in.size() == 0) { // Unused // If its entry is in the archive, flag it to be removed ArchiveEntry* entry = theResourceManager->getPatchEntry(p.name, "patches", archive); if (entry && entry->getParent() == archive) to_remove.push_back(entry); // Update texturex list patch indices for (unsigned t = 0; t < tx_lists.size(); t++) tx_lists[t]->removePatch(p.name); // Remove the patch from the patch table LOG_MESSAGE(1, "Removed patch %s", p.name); removed++; ptable.removePatch(a--); } } // Remove unused patch entries for (unsigned a = 0; a < to_remove.size(); a++) { LOG_MESSAGE(1, "Removed entry %s", to_remove[a]->getName()); archive->removeEntry(to_remove[a]); } // Write PNAMES changes ptable.writePNAMES(pnames); // Write TEXTUREx changes for (unsigned a = 0; a < tx_lists.size(); a++) tx_lists[a]->writeTEXTUREXData(tx_entries[a], ptable); // Cleanup for (unsigned a = 0; a < tx_lists.size(); a++) delete tx_lists[a]; // Notify user wxMessageBox( S_FMT("Removed %d patches and %lu entries. See console log for details.", removed, to_remove.size()), "Removed Unused Patches", wxOK | wxICON_INFORMATION); return true; }
/* ArchiveManager::closeArchive * Closes the archive at index, and removes it from the list if the * index is valid. Returns false on invalid index, true otherwise *******************************************************************/ bool ArchiveManager::closeArchive(int index) { // Check for invalid index if (index < 0 || index >= (int) open_archives.size()) return false; // Announce archive closing MemChunk mc; int32_t temp = index; mc.write(&temp, 4); announce("archive_closing", mc); // Delete any bookmarked entries contained in the archive deleteBookmarksInArchive(open_archives[index].archive); // Remove from resource manager theResourceManager->removeArchive(open_archives[index].archive); // Delete any embedded configuration //theGameConfiguration->removeEmbeddedConfig(open_archives[index].archive->getFilename()); // Close any open child archives // Clear out the open_children vector first, lest the children try to // remove themselves from it vector<Archive*> open_children = open_archives[index].open_children; open_archives[index].open_children.clear(); for (size_t a = 0; a < open_children.size(); a++) { int ci = archiveIndex(open_children[a]); if (ci >= 0) closeArchive(ci); } // Remove ourselves from our parent's open-child list ArchiveEntry* parent = open_archives[index].archive->getParent(); if (parent) { Archive* gp = parent->getParent(); if (gp) { int pi = archiveIndex(gp); if (pi >= 0) { vector<Archive*>& children = open_archives[pi].open_children; for (vector<Archive*>::iterator it = children.begin(); it < children.end(); it++) { if (*it == open_archives[index].archive) { children.erase(it, it + 1); break; } } } } } // Close the archive open_archives[index].archive->close(); // Delete the archive object delete open_archives[index].archive; // Remove the archive at index from the list open_archives.erase(open_archives.begin() + index); // Announce closed announce("archive_closed", mc); return true; }