void UnlinkCelCommand::onExecute(Context* context) { ContextWriter writer(context); Document* document(writer.document()); bool nonEditableLayers = false; { Transaction transaction(writer.context(), "Unlink Cel"); // TODO the range of selected frames should be in doc::Site. auto range = App::instance()->timeline()->range(); if (range.enabled()) { Sprite* sprite = writer.sprite(); for (LayerIndex layerIdx = range.layerBegin(); layerIdx <= range.layerEnd(); ++layerIdx) { Layer* layer = sprite->indexToLayer(layerIdx); if (!layer->isImage()) continue; LayerImage* layerImage = static_cast<LayerImage*>(layer); for (frame_t frame = range.frameEnd(), begin = range.frameBegin()-1; frame != begin; --frame) { Cel* cel = layerImage->cel(frame); if (cel && cel->links()) { if (layerImage->isEditable()) transaction.execute(new cmd::UnlinkCel(cel)); else nonEditableLayers = true; } } } } else { Cel* cel = writer.cel(); if (cel && cel->links()) { if (cel->layer()->isEditable()) transaction.execute(new cmd::UnlinkCel(writer.cel())); else nonEditableLayers = true; } } transaction.commit(); } if (nonEditableLayers) StatusBar::instance()->showTip(1000, "There are locked layers"); update_screen_for_document(document); }
void UnlinkCelCommand::onExecute(Context* context) { ContextWriter writer(context); Document* document(writer.document()); bool nonEditableLayers = false; { Transaction transaction(writer.context(), "Unlink Cel"); const Site* site = writer.site(); if (site->inTimeline() && !site->selectedLayers().empty()) { for (Layer* layer : site->selectedLayers()) { if (!layer->isImage()) continue; if (!layer->isEditableHierarchy()) { nonEditableLayers = true; continue; } LayerImage* layerImage = static_cast<LayerImage*>(layer); for (frame_t frame : site->selectedFrames().reversed()) { Cel* cel = layerImage->cel(frame); if (cel && cel->links()) transaction.execute(new cmd::UnlinkCel(cel)); } } } else { Cel* cel = writer.cel(); if (cel && cel->links()) { if (cel->layer()->isEditableHierarchy()) transaction.execute(new cmd::UnlinkCel(writer.cel())); else nonEditableLayers = true; } } transaction.commit(); } if (nonEditableLayers) StatusBar::instance()->showTip(1000, "There are locked layers"); update_screen_for_document(document); }
void CopyCel::onExecute() { LayerImage* srcLayer = static_cast<LayerImage*>(m_srcLayer.layer()); LayerImage* dstLayer = static_cast<LayerImage*>(m_dstLayer.layer()); ASSERT(srcLayer); ASSERT(dstLayer); Sprite* srcSprite = srcLayer->sprite(); Sprite* dstSprite = dstLayer->sprite(); ASSERT(srcSprite); ASSERT(dstSprite); ASSERT(m_srcFrame >= 0 && m_srcFrame < srcSprite->totalFrames()); ASSERT(m_dstFrame >= 0); (void)srcSprite; // To avoid unused variable warning on Release mode Cel* srcCel = srcLayer->cel(m_srcFrame); Cel* dstCel = dstLayer->cel(m_dstFrame); // Clear destination cel if it does exist. It'll be overriden by the // copy of srcCel. if (dstCel) { if (dstCel->links()) executeAndAdd(new cmd::UnlinkCel(dstCel)); executeAndAdd(new cmd::ClearCel(dstCel)); } // Add empty frames until newFrame while (dstSprite->totalFrames() <= m_dstFrame) executeAndAdd(new cmd::AddFrame(dstSprite, dstSprite->totalFrames())); Image* srcImage = (srcCel ? srcCel->image(): NULL); ImageRef dstImage; dstCel = dstLayer->cel(m_dstFrame); if (dstCel) dstImage = dstCel->imageRef(); bool createLink = (srcLayer == dstLayer && dstLayer->isContinuous()); // For background layer if (dstLayer->isBackground()) { ASSERT(dstCel); ASSERT(dstImage); if (!dstCel || !dstImage || !srcCel || !srcImage) return; if (createLink) { executeAndAdd(new cmd::SetCelData(dstCel, srcCel->dataRef())); } else { BlendMode blend = (srcLayer->isBackground() ? BlendMode::SRC: BlendMode::NORMAL); ImageRef tmp(Image::createCopy(dstImage.get())); render::composite_image(tmp.get(), srcImage, srcCel->x(), srcCel->y(), 255, blend); executeAndAdd(new cmd::CopyRect(dstImage.get(), tmp.get(), gfx::Clip(tmp->bounds()))); } } // For transparent layers else { if (dstCel) executeAndAdd(new cmd::RemoveCel(dstCel)); if (srcCel) { if (createLink) dstCel = Cel::createLink(srcCel); else dstCel = Cel::createCopy(srcCel); dstCel->setFrame(m_dstFrame); executeAndAdd(new cmd::AddCel(dstLayer, dstCel)); } } }
void FlattenLayers::onExecute() { Sprite* sprite = this->sprite(); auto doc = static_cast<Doc*>(sprite->document()); // Create a temporary image. ImageRef image(Image::create(sprite->pixelFormat(), sprite->width(), sprite->height())); LayerImage* flatLayer; // The layer onto which everything will be flattened. color_t bgcolor; // The background color to use for flatLayer. flatLayer = sprite->backgroundLayer(); if (flatLayer && flatLayer->isVisible()) { // There exists a visible background layer, so we will flatten onto that. bgcolor = doc->bgColor(flatLayer); } else { // Create a new transparent layer to flatten everything onto. flatLayer = new LayerImage(sprite); ASSERT(flatLayer->isVisible()); executeAndAdd(new cmd::AddLayer(sprite->root(), flatLayer, nullptr)); executeAndAdd(new cmd::SetLayerName(flatLayer, "Flattened")); bgcolor = sprite->transparentColor(); } render::Render render; render.setBgType(render::BgType::NONE); // Copy all frames to the background. for (frame_t frame(0); frame<sprite->totalFrames(); ++frame) { // Clear the image and render this frame. clear_image(image.get(), bgcolor); render.renderSprite(image.get(), sprite, frame); // TODO Keep cel links when possible ImageRef cel_image; Cel* cel = flatLayer->cel(frame); if (cel) { if (cel->links()) executeAndAdd(new cmd::UnlinkCel(cel)); cel_image = cel->imageRef(); ASSERT(cel_image); executeAndAdd(new cmd::CopyRect(cel_image.get(), image.get(), gfx::Clip(0, 0, image->bounds()))); } else { cel_image.reset(Image::createCopy(image.get())); cel = new Cel(frame, cel_image); flatLayer->addCel(cel); } } // Delete old layers. LayerList layers = sprite->root()->layers(); for (Layer* layer : layers) if (layer != flatLayer) executeAndAdd(new cmd::RemoveLayer(layer)); }