コード例 #1
0
ファイル: celmove.cpp プロジェクト: RobertLowe/aseprite
void move_cel(ContextWriter& writer)
{
  Document* document = writer.document();
  Sprite* sprite = writer.sprite();
  Cel *src_cel, *dst_cel;

  ASSERT(src_layer != NULL);
  ASSERT(dst_layer != NULL);
  ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames());
  ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames());

  if (src_layer->isBackground()) {
    copy_cel(writer);
    return;
  }

  src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame);
  dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame);

  UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument);

  /* remove the 'dst_cel' (if it exists) because it must be
     replaced with 'src_cel' */
  if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL))
    remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel);

  /* move the cel in the same layer */
  if (src_cel != NULL) {
    if (src_layer == dst_layer) {
      if (undo.isEnabled())
        undo.pushUndoer(new undoers::SetCelFrame(undo.getObjects(), src_cel));

      src_cel->setFrame(dst_frame);
    }
    /* move the cel in different layers */
    else {
      if (undo.isEnabled())
        undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), src_layer, src_cel));
      static_cast<LayerImage*>(src_layer)->removeCel(src_cel);

      src_cel->setFrame(dst_frame);

      /* if we are moving a cel from a transparent layer to the
         background layer, we have to clear the background of the
         image */
      if (!src_layer->isBackground() &&
          dst_layer->isBackground()) {
        Image *src_image = sprite->getStock()->getImage(src_cel->getImage());
        Image *dst_image = image_crop(src_image,
                                      -src_cel->getX(),
                                      -src_cel->getY(),
                                      sprite->getWidth(),
                                      sprite->getHeight(), 0);

        if (undo.isEnabled()) {
          undo.pushUndoer(new undoers::ReplaceImage(undo.getObjects(),
              sprite->getStock(), src_cel->getImage()));
          undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), src_cel));
          undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), src_cel));
        }

        image_clear(dst_image, app_get_color_to_clear_layer(dst_layer));
        image_merge(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL);

        src_cel->setPosition(0, 0);
        src_cel->setOpacity(255);

        sprite->getStock()->replaceImage(src_cel->getImage(), dst_image);
        image_free(src_image);
      }

      if (undo.isEnabled())
        undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, src_cel));

      static_cast<LayerImage*>(dst_layer)->addCel(src_cel);
    }
  }

  undo.commit();

  document->notifyCelMoved(src_layer, src_frame, dst_layer, dst_frame);
  set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0));
}
コード例 #2
0
void MergeDownLayerCommand::onExecute(Context* context)
{
  ContextWriter writer(context);
  Document* document(writer.document());
  Sprite* sprite(writer.sprite());
  Transaction transaction(writer.context(), "Merge Down Layer", ModifyDocument);
  LayerImage* src_layer = static_cast<LayerImage*>(writer.layer());
  Layer* dst_layer = src_layer->getPrevious();

  for (frame_t frpos = 0; frpos<sprite->totalFrames(); ++frpos) {
    // Get frames
    Cel* src_cel = src_layer->cel(frpos);
    Cel* dst_cel = dst_layer->cel(frpos);

    // Get images
    Image* src_image;
    if (src_cel != NULL)
      src_image = src_cel->image();
    else
      src_image = NULL;

    ImageRef dst_image;
    if (dst_cel)
      dst_image = dst_cel->imageRef();

    // With source image?
    if (src_image) {
      int t;
      int opacity;
      opacity = MUL_UN8(src_cel->opacity(), src_layer->opacity(), t);

      // No destination image
      if (!dst_image) {  // Only a transparent layer can have a null cel
        // Copy this cel to the destination layer...

        // Creating a copy of the image
        dst_image.reset(Image::createCopy(src_image));

        // Creating a copy of the cell
        dst_cel = new Cel(frpos, dst_image);
        dst_cel->setPosition(src_cel->x(), src_cel->y());
        dst_cel->setOpacity(opacity);

        transaction.execute(new cmd::AddCel(dst_layer, dst_cel));
      }
      // With destination
      else {
        gfx::Rect bounds;

        // Merge down in the background layer
        if (dst_layer->isBackground()) {
          bounds = sprite->bounds();
        }
        // Merge down in a transparent layer
        else {
          bounds = src_cel->bounds().createUnion(dst_cel->bounds());
        }

        doc::color_t bgcolor = app_get_color_to_clear_layer(dst_layer);

        ImageRef new_image(doc::crop_image(
            dst_image.get(),
            bounds.x-dst_cel->x(),
            bounds.y-dst_cel->y(),
            bounds.w, bounds.h, bgcolor));

        // Merge src_image in new_image
        render::composite_image(
          new_image.get(), src_image,
          sprite->palette(src_cel->frame()),
          src_cel->x()-bounds.x,
          src_cel->y()-bounds.y,
          opacity,
          src_layer->blendMode());

        transaction.execute(new cmd::SetCelPosition(dst_cel,
            bounds.x, bounds.y));

        if (dst_cel->links())
          transaction.execute(new cmd::UnlinkCel(dst_cel));

        transaction.execute(new cmd::ReplaceImage(sprite,
            dst_cel->imageRef(), new_image));
      }
    }
  }

  document->notifyLayerMergedDown(src_layer, dst_layer);
  document->getApi(transaction).removeLayer(src_layer); // src_layer is deleted inside removeLayer()

  transaction.commit();
  update_screen_for_document(document);
}
コード例 #3
0
ファイル: celmove.cpp プロジェクト: RobertLowe/aseprite
void copy_cel(ContextWriter& writer)
{
  Document* document = writer.document();
  Sprite* sprite = writer.sprite();
  UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument);
  Cel *src_cel, *dst_cel;

  ASSERT(src_layer != NULL);
  ASSERT(dst_layer != NULL);
  ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames());
  ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames());

  src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame);
  dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame);

  // Remove the 'dst_cel' (if it exists) because it must be replaced
  // with 'src_cel'
  if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL))
    remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel);

  // Move the cel in the same layer.
  if (src_cel != NULL) {
    Image *src_image = sprite->getStock()->getImage(src_cel->getImage());
    Image *dst_image;
    int image_index;
    int dst_cel_x;
    int dst_cel_y;
    int dst_cel_opacity;

    // If we are moving a cel from a transparent layer to the
    // background layer, we have to clear the background of the image.
    if (!src_layer->isBackground() &&
        dst_layer->isBackground()) {
      dst_image = image_crop(src_image,
                             -src_cel->getX(),
                             -src_cel->getY(),
                             sprite->getWidth(),
                             sprite->getHeight(), 0);

      image_clear(dst_image, app_get_color_to_clear_layer(dst_layer));
      image_merge(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL);

      dst_cel_x = 0;
      dst_cel_y = 0;
      dst_cel_opacity = 255;
    }
    else {
      dst_image = Image::createCopy(src_image);
      dst_cel_x = src_cel->getX();
      dst_cel_y = src_cel->getY();
      dst_cel_opacity = src_cel->getOpacity();
    }

    // Add the image in the stock
    image_index = sprite->getStock()->addImage(dst_image);
    if (undo.isEnabled())
      undo.pushUndoer(new undoers::AddImage(undo.getObjects(),
          sprite->getStock(), image_index));

    // Create the new cel
    dst_cel = new Cel(dst_frame, image_index);
    dst_cel->setPosition(dst_cel_x, dst_cel_y);
    dst_cel->setOpacity(dst_cel_opacity);

    if (undo.isEnabled())
      undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, dst_cel));

    static_cast<LayerImage*>(dst_layer)->addCel(dst_cel);
  }

  undo.commit();

  document->notifyCelCopied(src_layer, src_frame, dst_layer, dst_frame);
  set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0));
}
コード例 #4
0
ファイル: cmd_flip.cpp プロジェクト: atzkey/aseprite
void FlipCommand::onExecute(Context* context)
{
  ContextWriter writer(context);
  Document* document = writer.document();
  Sprite* sprite = writer.sprite();
  DocumentApi api = document->getApi();

  {
    UndoTransaction undoTransaction(writer.context(),
                                    m_flipMask ?
                                    (m_flipType == raster::algorithm::FlipHorizontal ?
                                     "Flip Horizontal":
                                     "Flip Vertical"):
                                    (m_flipType == raster::algorithm::FlipHorizontal ?
                                     "Flip Canvas Horizontal":
                                     "Flip Canvas Vertical"));

    if (m_flipMask) {
      int x, y;
      Image* image = writer.image(&x, &y);
      if (!image)
        return;

      Mask* mask = NULL;
      bool alreadyFlipped = false;

      // This variable will be the area to be flipped inside the image.
      gfx::Rect bounds(image->getBounds());

      // If there is some portion of sprite selected, we flip the
      // selected region only. If the mask isn't visible, we flip the
      // whole image.
      if (document->isMaskVisible()) {
        mask = document->getMask();

        // Intersect the full area of the image with the mask's
        // bounds, so we don't request to flip an area outside the
        // image's bounds.
        bounds = bounds.createIntersect(gfx::Rect(mask->getBounds()).offset(-x, -y));

        // If the mask isn't a rectangular area, we've to flip the mask too.
        if (mask->getBitmap() != NULL && !mask->isRectangular()) {
          int bgcolor = app_get_color_to_clear_layer(writer.layer());

          // Flip the portion of image specified by the mask.
          mask->offsetOrigin(-x, -y);
          api.flipImageWithMask(image, mask, m_flipType, bgcolor);
          mask->offsetOrigin(x, y);
          alreadyFlipped = true;

          // Flip the mask.
          Image* maskBitmap = mask->getBitmap();
          if (maskBitmap != NULL) {
            // Create a flipped copy of the current mask.
            base::UniquePtr<Mask> newMask(new Mask(*mask));
            newMask->freeze();
            raster::algorithm::flip_image(newMask->getBitmap(),
              maskBitmap->getBounds(), m_flipType);
            newMask->unfreeze();

            // Change the current mask and generate the new boundaries.
            api.copyToCurrentMask(newMask);

            document->generateMaskBoundaries();
          }
        }
      }

      // Flip the portion of image specified by "bounds" variable.
      if (!alreadyFlipped) {
        api.flipImage(image, bounds, m_flipType);
      }
    }
    else {
      // get all sprite cels
      CelList cels;
      sprite->getCels(cels);

      // for each cel...
      for (CelIterator it = cels.begin(); it != cels.end(); ++it) {
        Cel* cel = *it;
        Image* image = sprite->getStock()->getImage(cel->getImage());

        api.setCelPosition
          (sprite, cel,
           (m_flipType == raster::algorithm::FlipHorizontal ?
            sprite->getWidth() - image->getWidth() - cel->getX():
            cel->getX()),
           (m_flipType == raster::algorithm::FlipVertical ?
            sprite->getHeight() - image->getHeight() - cel->getY():
            cel->getY()));

        api.flipImage(image, image->getBounds(), m_flipType);
      }
    }

    undoTransaction.commit();
  }

  update_screen_for_document(document);
}