/* PaletteManager::loadCustomPalettes * Loads any files in the '<userdir>/palettes' directory as palettes, * with names from the files (minus the file extension) *******************************************************************/ bool PaletteManager::loadCustomPalettes() { // If the directory doesn't exist create it if (!wxDirExists(appPath("palettes", DIR_USER))) wxMkdir(appPath("palettes", DIR_USER)); // Open the custom palettes directory wxDir res_dir; res_dir.Open(appPath("palettes", DIR_USER)); // Go through each file in the directory string filename = wxEmptyString; bool files = res_dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES); while (files) { // Load palette data Palette8bit* pal = new Palette8bit(); MemChunk mc; mc.importFile(res_dir.GetName() + "/" + filename); pal->loadMem(mc); // Add the palette wxFileName fn(filename); addPalette(pal, fn.GetName()); // Next file files = res_dir.GetNext(&filename); } return true; }
/* PaletteEntryPanel::loadEntry * Reads all palettes in the PLAYPAL entry and shows the first one *******************************************************************/ bool PaletteEntryPanel::loadEntry(ArchiveEntry* entry) { // Clear any existing palettes for (size_t a = 0; a < palettes.size(); a++) delete palettes[a]; palettes.clear(); // Determine how many palettes are in the entry int n_palettes = entry->getSize() / 768; // Load each palette entry->seek(0, SEEK_SET); uint8_t pal_data[768]; for (int a = 0; a < n_palettes; a++) { // Read palette data entry->read(&pal_data, 768); // Create palette Palette8bit* pal = new Palette8bit(); pal->loadMem(pal_data, 768); // Add palette palettes.push_back(pal); } // Show first palette cur_palette = 0; showPalette(0); setModified(false); return true; }
bool readImage(SImage& image, MemChunk& data, int index) { // Get image info SImage::info_t info; FIBITMAP* bm = getFIInfo(data, info); // Check it created/read ok if (!bm) { Global::error = "Unable to read image data (unsupported format?)"; return false; } // Get image palette if it exists RGBQUAD* bm_pal = FreeImage_GetPalette(bm); Palette8bit palette; if (bm_pal) { int a = 0; int b = FreeImage_GetColorsUsed(bm); if (b > 256) b = 256; for (; a < b; a++) palette.setColour(a, rgba_t(bm_pal[a].rgbRed, bm_pal[a].rgbGreen, bm_pal[a].rgbBlue, 255)); } // Create image if (info.has_palette) image.create(info, &palette); else image.create(info); uint8_t* img_data = imageData(image); // Convert to 32bpp & flip vertically FIBITMAP* rgba = FreeImage_ConvertTo32Bits(bm); FreeImage_FlipVertical(rgba); // Load raw RGBA data uint8_t* bits_rgba = FreeImage_GetBits(rgba); int c = 0; for (int a = 0; a < info.width * info.height; a++) { img_data[c++] = bits_rgba[a * 4 + 2]; // Red img_data[c++] = bits_rgba[a * 4 + 1]; // Green img_data[c++] = bits_rgba[a * 4]; // Blue img_data[c++] = bits_rgba[a * 4 + 3]; // Alpha } // Free memory FreeImage_Unload(rgba); FreeImage_Unload(bm); return true; }
/* PaletteEntryPanel::duplicate * Make a copy of the current palette and add it to the list *******************************************************************/ bool PaletteEntryPanel::duplicate() { Palette8bit* newpalette = new Palette8bit; if (!newpalette) return false; newpalette->copyPalette(palettes[cur_palette]); palettes.push_back(newpalette); // Refresh the display to show the updated amount of palettes showPalette(cur_palette); setModified(); return true; }
/* PaletteEntryPanel::testPalette * A "lite" version of addCustomPalette, which does not add to the * palette folder so the palette is only available for the current * session. *******************************************************************/ bool PaletteEntryPanel::testPalette() { // Get name to export as string name = "Test: " + wxGetTextFromUser("Enter name for Palette:", "Test Palettes"); // Add to palette manager and main palette chooser Palette8bit* pal = new Palette8bit(); pal->copyPalette(palettes[cur_palette]); thePaletteManager->addPalette(pal, name); thePaletteChooser->addPalette(name); thePaletteChooser->selectPalette(name); return true; }
/* PaletteEntryPanel::tweak * Tweaks the colours of the current palette *******************************************************************/ bool PaletteEntryPanel::tweak() { Palette8bit* pal = new Palette8bit; if (pal == NULL) return false; pal->copyPalette(palettes[cur_palette]); PaletteColourTweakDialog pctd(theMainWindow, pal); if (pctd.ShowModal() == wxID_OK) { palettes[cur_palette]->copyPalette(pctd.getFinalPalette()); showPalette(cur_palette); setModified(); } delete pal; return true; }
/* PaletteEntryPanel::generatePalette * Just a helper for generatePalettes to make the code less redundant *******************************************************************/ void PaletteEntryPanel::generatePalette(int r, int g, int b, int shift, int steps) { // Create a new palette Palette8bit* pal = new Palette8bit; if (pal == NULL) return; // Seed it with the basic palette pal->copyPalette(palettes[0]); // Tint palette with given values pal->idtint(r, g, b, shift, steps); // Add it to the palette list palettes.push_back(pal); }
/* SImage::shrinkPalette * Shifts all the used colours to the beginning of the palette *******************************************************************/ void SImage::shrinkPalette(Palette8bit* pal) { // If the picture is not paletted, stop. if (type != PALMASK) return; // Get palette to use if (has_palette || !pal) pal = &palette; // Init variables Palette8bit newpal; bool* usedcolours = new bool[256]; int* remap = new int[256]; memset(usedcolours, 0, 256); size_t used = 0; // Count all color indices actually used on the picture for (int a = 0; a < width*height; ++a) { usedcolours[data[a]] = true; } // Create palette remapping information for (size_t b = 0; b < 256; ++b) { if (usedcolours[b]) { newpal.setColour(used, pal->colour(b)); remap[b] = used; ++used; } } // Remap image to new palette indices for (int c = 0; c < width*height; ++c) { data[c] = remap[data[c]]; } pal->copyPalette(&newpal); // Cleanup delete[] usedcolours; delete[] remap; }
/* PaletteEntryPanel::addCustomPalette * Adds the current palette to the custom user palettes folder, so * it can be selected via the palette selector *******************************************************************/ bool PaletteEntryPanel::addCustomPalette() { // Get name to export as string name = wxGetTextFromUser("Enter name for Palette:", "Add to Palettes"); if (name.IsEmpty()) return false; // Write current palette to the user palettes directory string path = appPath(S_FMT("palettes/%s.pal", name), DIR_USER); palettes[cur_palette]->saveFile(path); // Add to palette manager and main palette chooser Palette8bit* pal = new Palette8bit(); pal->copyPalette(palettes[cur_palette]); thePaletteManager->addPalette(pal, name); thePaletteChooser->addPalette(name); return true; }
/* PaletteManager::loadResourcePalettes * Loads any entries in the 'palettes' directory of SLADE.pk3 as * palettes, with names from the entries (minus the entry extension) *******************************************************************/ bool PaletteManager::loadResourcePalettes() { // Get the 'palettes' directory of SLADE.pk3 Archive* res_archive = theArchiveManager->programResourceArchive(); ArchiveTreeNode* dir_palettes = res_archive->getDir("palettes/"); // Check it exists if (!dir_palettes) return false; // Go through all entries in the directory for (size_t a = 0; a < dir_palettes->numEntries(); a++) { // Load palette data Palette8bit* pal = new Palette8bit(); MemChunk mc(dir_palettes->getEntry(a)->getData(true), dir_palettes->getEntry(a)->getSize()); pal->loadMem(mc); // Add the palette addPalette(pal, dir_palettes->getEntry(a)->getName(true)); } return true; }
GLTexture* MapTextureManager::getSprite(string name, string translation, string palette) { // Don't bother looking for nameless sprites if (name.IsEmpty()) return NULL; // Get sprite matching name string hashname = name.Upper(); if (!translation.IsEmpty()) hashname += translation.Lower(); if (!palette.IsEmpty()) hashname += palette.Upper(); map_tex_t& mtex = sprites[hashname]; // Get desired filter type int filter = 1; if (map_tex_filter == 0) filter = GLTexture::NEAREST_LINEAR_MIN; else if (map_tex_filter == 1) filter = GLTexture::LINEAR; else if (map_tex_filter == 2) filter = GLTexture::LINEAR; else if (map_tex_filter == 3) filter = GLTexture::NEAREST_MIPMAP; // If the texture is loaded if (mtex.texture) { // If the texture filter matches the desired one, return it if (mtex.texture->getFilter() == filter) return mtex.texture; else { // Otherwise, reload the texture delete mtex.texture; mtex.texture = NULL; } } // Sprite not found, look for it bool found = false; bool mirror = false; SImage image; Palette8bit* pal = getResourcePalette(); ArchiveEntry* entry = theResourceManager->getPatchEntry(name, "sprites", archive); if (!entry) entry = theResourceManager->getPatchEntry(name, "", archive); if (!entry && name.length() == 8) { string newname = name; newname[4] = name[6]; newname[5] = name[7]; newname[6] = name[4]; newname[7] = name[5]; entry = theResourceManager->getPatchEntry(newname, "sprites", archive); if (entry) mirror = true; } if (entry) { found = true; Misc::loadImageFromEntry(&image, entry); } else // Try composite textures then { CTexture* ctex = theResourceManager->getTexture(name, archive); if (ctex && ctex->toImage(image, archive, pal)) found = true; } // We have a valid image either from an entry or a composite texture. if (found) { // Apply translation if (!translation.IsEmpty()) image.applyTranslation(translation, pal); // Apply palette override if (!palette.IsEmpty()) { ArchiveEntry* newpal = theResourceManager->getPaletteEntry(palette, archive); if (newpal && newpal->getSize() == 768) { // Why is this needed? // Copying data in pal->loadMem shouldn't // change it in the original entry... // We shouldn't need to copy the data in a temporary place first. pal = image.getPalette(); MemChunk mc; mc.importMem(newpal->getData(), newpal->getSize()); pal->loadMem(mc); } } // Apply mirroring if (mirror) image.mirror(false); // Turn into GL texture mtex.texture = new GLTexture(false); mtex.texture->setFilter(filter); mtex.texture->setTiling(false); mtex.texture->loadImage(&image, pal); return mtex.texture; } else if (name.EndsWith("?")) { name.RemoveLast(1); GLTexture* sprite = getSprite(name + '0', translation, palette); if (!sprite) sprite = getSprite(name + '1', translation, palette); if (sprite) return sprite; if (!sprite && name.length() == 5) { for (char chr = 'A'; chr <= ']'; ++chr) { sprite = getSprite(name + '0' + chr + '0', translation, palette); if (sprite) return sprite; sprite = getSprite(name + '1' + chr + '1', translation, palette); if (sprite) return sprite; } } } return NULL; }