/* CTexture::loadPatchImage * Loads the image for the patch at [pindex] into [image]. Can deal * with textures-as-patches *******************************************************************/ bool CTexture::loadPatchImage(unsigned pindex, SImage& image, Archive* parent, Palette8bit* pal) { // Check patch index if (pindex >= patches.size()) return false; CTPatch* patch = patches[pindex]; // If the texture is extended, search for textures-as-patches first // (as long as the patch name is different from this texture's name) if (extended && !(S_CMPNOCASE(patch->getName(), name))) { // Search the texture list we're in first if (in_list) { for (unsigned a = 0; a < in_list->nTextures(); a++) { CTexture* tex = in_list->getTexture(a); // Don't look past this texture in the list if (tex->getName() == name) break; // Check for name match if (S_CMPNOCASE(tex->getName(), patch->getName())) { // Load texture to image return tex->toImage(image, parent, pal); } } } // Otherwise, try the resource manager // TODO: Something has to be ignored here. The entire archive or just the current list? CTexture* tex = theResourceManager->getTexture(patch->getName(), parent); if (tex) return tex->toImage(image, parent, pal); } // Get patch entry ArchiveEntry* entry = patch->getPatchEntry(parent); // Load entry to image if valid if (entry) return Misc::loadImageFromEntry(&image, entry); else return false; }
/* 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; }
/* CTexture::toImage * Generates a SImage representation of this texture, using patches * from [parent] primarily, and the palette [pal] *******************************************************************/ bool CTexture::toImage(SImage& image, Archive* parent, Palette8bit* pal, bool force_rgba) { // Init image image.clear(); image.resize(width, height); // Add patches SImage p_img(PALMASK); si_drawprops_t dp; dp.src_alpha = false; if (defined) { CTPatchEx* patch = (CTPatchEx*)patches[0]; if (!loadPatchImage(0, p_img, parent, pal)) return false; width = p_img.getWidth(); height = p_img.getHeight(); image.resize(width, height); scale_x = (double)width / (double)def_width; scale_y = (double)height / (double)def_height; image.drawImage(p_img, 0, 0, dp, pal, pal); } else if (extended) { // Extended texture // Add each patch to image for (unsigned a = 0; a < patches.size(); a++) { CTPatchEx* patch = (CTPatchEx*)patches[a]; // Load patch entry if (!loadPatchImage(a, p_img, parent, pal)) continue; // Handle offsets int ofs_x = patch->xOffset(); int ofs_y = patch->yOffset(); if (patch->useOffsets()) { ofs_x -= p_img.offset().x; ofs_y -= p_img.offset().y; } // Apply translation before anything in case we're forcing rgba (can't translate rgba images) if (patch->getBlendType() == 1) p_img.applyTranslation(&(patch->getTranslation()), pal); // Convert to RGBA if forced if (force_rgba) p_img.convertRGBA(pal); // Flip/rotate if needed if (patch->flipX()) p_img.mirror(false); if (patch->flipY()) p_img.mirror(true); if (patch->getRotation() != 0) p_img.rotate(patch->getRotation()); // Setup transparency blending dp.blend = NORMAL; dp.alpha = 1.0f; dp.src_alpha = false; if (patch->getStyle() == "CopyAlpha" || patch->getStyle() == "Overlay") dp.src_alpha = true; else if (patch->getStyle() == "Translucent" || patch->getStyle() == "CopyNewAlpha") dp.alpha = patch->getAlpha(); else if (patch->getStyle() == "Add") { dp.blend = ADD; dp.alpha = patch->getAlpha(); } else if (patch->getStyle() == "Subtract") { dp.blend = SUBTRACT; dp.alpha = patch->getAlpha(); } else if (patch->getStyle() == "ReverseSubtract") { dp.blend = REVERSE_SUBTRACT; dp.alpha = patch->getAlpha(); } else if (patch->getStyle() == "Modulate") { dp.blend = MODULATE; dp.alpha = patch->getAlpha(); } // Setup patch colour if (patch->getBlendType() == 2) p_img.colourise(patch->getColour(), pal); else if (patch->getBlendType() == 3) p_img.tint(patch->getColour(), patch->getColour().fa(), pal); // Add patch to texture image image.drawImage(p_img, ofs_x, ofs_y, dp, pal, pal); } } else { // Normal texture // Add each patch to image for (unsigned a = 0; a < patches.size(); a++) { CTPatch* patch = patches[a]; if (Misc::loadImageFromEntry(&p_img, patch->getPatchEntry(parent))) image.drawImage(p_img, patch->xOffset(), patch->yOffset(), dp, pal, pal); } } return true; }