mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-28 16:20:50 +00:00
Replace doc::Stock with doc::ImageRef shared pointer
Changes: * Add doc::ImageRef to count references to the same image between Cels (at this moment we cannot generate linked cels anyway) * Remove doc:Stock class and doc::Sprite::m_stock member variable * Remove app::undoers::Add/RemoveImage * Add doc::SubObjectsIO and app::undoers::ObjectIO to replace doc::LayerSubObjectsSerializer
This commit is contained in:
parent
1b55fe39dc
commit
f1f24cbcdd
@ -265,7 +265,6 @@ add_library(app-lib
|
||||
undo_transaction.cpp
|
||||
undoers/add_cel.cpp
|
||||
undoers/add_frame.cpp
|
||||
undoers/add_image.cpp
|
||||
undoers/add_layer.cpp
|
||||
undoers/add_palette.cpp
|
||||
undoers/close_group.cpp
|
||||
@ -274,11 +273,11 @@ add_library(app-lib
|
||||
undoers/image_area.cpp
|
||||
undoers/modified_region.cpp
|
||||
undoers/move_layer.cpp
|
||||
undoers/object_io.cpp
|
||||
undoers/open_group.cpp
|
||||
undoers/remap_palette.cpp
|
||||
undoers/remove_cel.cpp
|
||||
undoers/remove_frame.cpp
|
||||
undoers/remove_image.cpp
|
||||
undoers/remove_layer.cpp
|
||||
undoers/remove_palette.cpp
|
||||
undoers/replace_image.cpp
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
namespace app {
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "doc/palette.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#include "generated_export_sprite_sheet.h"
|
||||
@ -327,7 +326,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
if (sheet_h == 0) sheet_h = sprite->height()*((nframes/columns)+((nframes%columns)>0?1:0));
|
||||
columns = sheet_w / sprite->width();
|
||||
|
||||
base::UniquePtr<Image> resultImage(Image::create(sprite->pixelFormat(), sheet_w, sheet_h));
|
||||
ImageRef resultImage(Image::create(sprite->pixelFormat(), sheet_w, sheet_h));
|
||||
doc::clear_image(resultImage, 0);
|
||||
|
||||
render::Render render;
|
||||
@ -360,12 +359,8 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
// Add the layer in the sprite.
|
||||
LayerImage* resultLayer = api.newLayer(sprite);
|
||||
|
||||
// Add the image into the sprite's stock
|
||||
int indexInStock = api.addImageInStock(sprite, resultImage);
|
||||
resultImage.release();
|
||||
|
||||
// Create the cel.
|
||||
base::UniquePtr<Cel> resultCel(new Cel(frame_t(0), indexInStock));
|
||||
base::UniquePtr<Cel> resultCel(new Cel(frame_t(0), resultImage));
|
||||
|
||||
// Add the cel in the layer.
|
||||
api.addCel(resultLayer, resultCel);
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "doc/layer.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "doc/palette.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
namespace app {
|
||||
@ -160,7 +159,7 @@ protected:
|
||||
}
|
||||
|
||||
// The list of frames imported from the sheet
|
||||
std::vector<Image*> animation;
|
||||
std::vector<ImageRef> animation;
|
||||
|
||||
try {
|
||||
Sprite* sprite = m_document->sprite();
|
||||
@ -170,7 +169,7 @@ protected:
|
||||
// As first step, we cut each tile and add them into "animation" list.
|
||||
for (int y=m_rect.y; y<sprite->height(); y += m_rect.h) {
|
||||
for (int x=m_rect.x; x<sprite->width(); x += m_rect.w) {
|
||||
base::UniquePtr<Image> resultImage(
|
||||
ImageRef resultImage(
|
||||
Image::create(sprite->pixelFormat(), m_rect.w, m_rect.h));
|
||||
|
||||
// Render the portion of sheet.
|
||||
@ -178,7 +177,6 @@ protected:
|
||||
gfx::Clip(0, 0, x, y, m_rect.w, m_rect.h));
|
||||
|
||||
animation.push_back(resultImage);
|
||||
resultImage.release();
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,14 +199,8 @@ protected:
|
||||
|
||||
// Add all frames+cels to the new layer
|
||||
for (size_t i=0; i<animation.size(); ++i) {
|
||||
int indexInStock;
|
||||
|
||||
// Add the image into the sprite's stock
|
||||
indexInStock = api.addImageInStock(sprite, animation[i]);
|
||||
animation[i] = NULL;
|
||||
|
||||
// Create the cel.
|
||||
base::UniquePtr<Cel> resultCel(new Cel(frame_t(i), indexInStock));
|
||||
base::UniquePtr<Cel> resultCel(new Cel(frame_t(i), animation[i]));
|
||||
|
||||
// Add the cel in the layer.
|
||||
api.addCel(resultLayer, resultCel);
|
||||
@ -233,8 +225,6 @@ protected:
|
||||
undoTransaction.commit();
|
||||
}
|
||||
catch (...) {
|
||||
for (size_t i=0; i<animation.size(); ++i)
|
||||
delete animation[i];
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/undo_transaction.h"
|
||||
#include "app/undoers/add_cel.h"
|
||||
#include "app/undoers/add_image.h"
|
||||
#include "app/undoers/remove_layer.h"
|
||||
#include "app/undoers/replace_image.h"
|
||||
#include "app/undoers/set_cel_position.h"
|
||||
@ -38,7 +37,6 @@
|
||||
#include "doc/layer.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "render/render.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
@ -87,7 +85,6 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
UndoTransaction undo(writer.context(), "Merge Down Layer", undo::ModifyDocument);
|
||||
Layer* src_layer = writer.layer();
|
||||
Layer* dst_layer = src_layer->getPrevious();
|
||||
int index;
|
||||
|
||||
for (frame_t frpos = 0; frpos<sprite->totalFrames(); ++frpos) {
|
||||
// Get frames
|
||||
@ -101,29 +98,21 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
else
|
||||
src_image = NULL;
|
||||
|
||||
Image* dst_image;
|
||||
if (dst_cel != NULL)
|
||||
dst_image = dst_cel->image();
|
||||
else
|
||||
dst_image = NULL;
|
||||
ImageRef dst_image;
|
||||
if (dst_cel)
|
||||
dst_image = dst_cel->imageRef();
|
||||
|
||||
// With source image?
|
||||
if (src_image != NULL) {
|
||||
if (src_image) {
|
||||
// No destination image
|
||||
if (dst_image == NULL) { // Only a transparent layer can have a null cel
|
||||
// Copy this cel to the destination layer...
|
||||
|
||||
// Creating a copy of the image
|
||||
dst_image = Image::createCopy(src_image);
|
||||
|
||||
// Adding it in the stock of images
|
||||
index = sprite->stock()->addImage(dst_image);
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::AddImage(
|
||||
undo.getObjects(), sprite->stock(), index));
|
||||
dst_image.reset(Image::createCopy(src_image));
|
||||
|
||||
// Creating a copy of the cell
|
||||
dst_cel = new Cel(frpos, index);
|
||||
dst_cel = new Cel(frpos, dst_image);
|
||||
dst_cel->setPosition(src_cel->x(), src_cel->y());
|
||||
dst_cel->setOpacity(src_cel->opacity());
|
||||
|
||||
@ -153,10 +142,10 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
|
||||
doc::color_t bgcolor = app_get_color_to_clear_layer(dst_layer);
|
||||
|
||||
Image* new_image = doc::crop_image(dst_image,
|
||||
x1-dst_cel->x(),
|
||||
y1-dst_cel->y(),
|
||||
x2-x1+1, y2-y1+1, bgcolor);
|
||||
ImageRef new_image(doc::crop_image(dst_image,
|
||||
x1-dst_cel->x(),
|
||||
y1-dst_cel->y(),
|
||||
x2-x1+1, y2-y1+1, bgcolor));
|
||||
|
||||
// Merge src_image in new_image
|
||||
render::composite_image(new_image, src_image,
|
||||
@ -172,10 +161,9 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::ReplaceImage(undo.getObjects(),
|
||||
sprite->stock(), dst_cel->imageIndex()));
|
||||
sprite, dst_cel->image(), new_image));
|
||||
|
||||
sprite->stock()->replaceImage(dst_cel->imageIndex(), new_image);
|
||||
delete dst_image;
|
||||
sprite->replaceImage(dst_cel->image()->id(), new_image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "doc/palette.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#include "generated_new_sprite.h"
|
||||
|
@ -52,7 +52,6 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "gfx/hsv.h"
|
||||
#include "gfx/rgb.h"
|
||||
#include "gfx/size.h"
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
namespace app {
|
||||
@ -116,12 +115,12 @@ protected:
|
||||
}
|
||||
|
||||
// rotate the image
|
||||
Image* new_image = Image::create(image->pixelFormat(),
|
||||
m_angle == 180 ? image->width(): image->height(),
|
||||
m_angle == 180 ? image->height(): image->width());
|
||||
ImageRef new_image(Image::create(image->pixelFormat(),
|
||||
m_angle == 180 ? image->width(): image->height(),
|
||||
m_angle == 180 ? image->height(): image->width()));
|
||||
doc::rotate_image(image, new_image, m_angle);
|
||||
|
||||
api.replaceStockImage(m_sprite, cel->imageIndex(), new_image);
|
||||
api.replaceImage(m_sprite, cel->imageRef(), new_image);
|
||||
}
|
||||
|
||||
jobProgress((float)i / m_cels.size());
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "doc/mask.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#define PERC_FORMAT "%.1f"
|
||||
@ -105,15 +104,15 @@ protected:
|
||||
// Resize the image
|
||||
int w = scale_x(image->width());
|
||||
int h = scale_y(image->height());
|
||||
Image* new_image = Image::create(image->pixelFormat(), MAX(1, w), MAX(1, h));
|
||||
ImageRef new_image(Image::create(image->pixelFormat(), MAX(1, w), MAX(1, h)));
|
||||
|
||||
doc::algorithm::fixup_image_transparent_colors(image);
|
||||
doc::algorithm::resize_image(image, new_image,
|
||||
m_resize_method,
|
||||
m_sprite->palette(cel->frame()),
|
||||
m_sprite->rgbMap(cel->frame()));
|
||||
m_resize_method,
|
||||
m_sprite->palette(cel->frame()),
|
||||
m_sprite->rgbMap(cel->frame()));
|
||||
|
||||
api.replaceStockImage(m_sprite, cel->imageIndex(), new_image);
|
||||
api.replaceImage(m_sprite, cel->imageRef(), new_image);
|
||||
|
||||
jobProgress((float)progress / cels.size());
|
||||
|
||||
@ -124,7 +123,7 @@ protected:
|
||||
|
||||
// Resize mask
|
||||
if (m_document->isMaskVisible()) {
|
||||
base::UniquePtr<Image> old_bitmap
|
||||
ImageRef old_bitmap
|
||||
(crop_image(m_document->mask()->bitmap(), -1, -1,
|
||||
m_document->mask()->bitmap()->width()+2,
|
||||
m_document->mask()->bitmap()->height()+2, 0));
|
||||
@ -137,9 +136,9 @@ protected:
|
||||
scale_x(m_document->mask()->bounds().x-1),
|
||||
scale_y(m_document->mask()->bounds().y-1), MAX(1, w), MAX(1, h)));
|
||||
algorithm::resize_image(old_bitmap, new_mask->bitmap(),
|
||||
m_resize_method,
|
||||
m_sprite->palette(0), // Ignored
|
||||
m_sprite->rgbMap(0)); // Ignored
|
||||
m_resize_method,
|
||||
m_sprite->palette(0), // Ignored
|
||||
m_sprite->rgbMap(0)); // Ignored
|
||||
|
||||
// Reshrink
|
||||
new_mask->intersect(new_mask->bounds());
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "doc/layer.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/view.h"
|
||||
#include "ui/widget.h"
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "app/file/format_options.h"
|
||||
#include "app/flatten.h"
|
||||
#include "app/objects_container_impl.h"
|
||||
#include "app/undoers/add_image.h"
|
||||
#include "app/undoers/add_layer.h"
|
||||
#include "app/util/boundary.h"
|
||||
#include "base/memory.h"
|
||||
@ -41,7 +40,6 @@
|
||||
#include "doc/mask.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -235,10 +233,9 @@ void Document::generateMaskBoundaries(Mask* mask)
|
||||
void Document::destroyExtraCel()
|
||||
{
|
||||
delete m_extraCel;
|
||||
delete m_extraImage;
|
||||
|
||||
m_extraCel = NULL;
|
||||
m_extraImage = NULL;
|
||||
m_extraImage.reset(NULL);
|
||||
}
|
||||
|
||||
void Document::prepareExtraCel(const gfx::Rect& bounds, int opacity)
|
||||
@ -246,7 +243,7 @@ void Document::prepareExtraCel(const gfx::Rect& bounds, int opacity)
|
||||
ASSERT(sprite() != NULL);
|
||||
|
||||
if (!m_extraCel)
|
||||
m_extraCel = new Cel(frame_t(0), 0); // Ignored fields for this cell (frame, and image index)
|
||||
m_extraCel = new Cel(frame_t(0), ImageRef(NULL)); // Ignored fields for this cel (frame, and image index)
|
||||
|
||||
m_extraCel->setPosition(bounds.getOrigin());
|
||||
m_extraCel->setOpacity(opacity);
|
||||
@ -255,9 +252,8 @@ void Document::prepareExtraCel(const gfx::Rect& bounds, int opacity)
|
||||
m_extraImage->pixelFormat() != sprite()->pixelFormat() ||
|
||||
m_extraImage->width() != bounds.w ||
|
||||
m_extraImage->height() != bounds.h) {
|
||||
delete m_extraImage; // image
|
||||
m_extraImage = Image::create(sprite()->pixelFormat(),
|
||||
bounds.w, bounds.h);
|
||||
m_extraImage.reset(Image::create(sprite()->pixelFormat(),
|
||||
bounds.w, bounds.h));
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +264,7 @@ Cel* Document::getExtraCel() const
|
||||
|
||||
Image* Document::getExtraCelImage() const
|
||||
{
|
||||
return m_extraImage;
|
||||
return m_extraImage.get();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -342,8 +338,8 @@ void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, La
|
||||
const Image* sourceImage = sourceCel->image();
|
||||
ASSERT(sourceImage != NULL);
|
||||
|
||||
Image* newImage = Image::createCopy(sourceImage);
|
||||
newCel->setImage(destLayer->sprite()->stock()->addImage(newImage));
|
||||
ImageRef newImage(Image::createCopy(sourceImage));
|
||||
newCel->setImage(newImage);
|
||||
|
||||
destLayer->addCel(newCel);
|
||||
newCel.release();
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "base/unique_ptr.h"
|
||||
#include "doc/document.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/pixel_format.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "gfx/transformation.h"
|
||||
@ -39,7 +40,6 @@ namespace base {
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
class Image;
|
||||
class Layer;
|
||||
class Mask;
|
||||
class Sprite;
|
||||
@ -219,7 +219,7 @@ namespace app {
|
||||
Cel* m_extraCel;
|
||||
|
||||
// Image of the extra cel.
|
||||
Image* m_extraImage;
|
||||
ImageRef m_extraImage;
|
||||
int m_extraCelBlendMode;
|
||||
|
||||
// Current mask.
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "app/settings/settings.h"
|
||||
#include "app/undoers/add_cel.h"
|
||||
#include "app/undoers/add_frame.h"
|
||||
#include "app/undoers/add_image.h"
|
||||
#include "app/undoers/add_layer.h"
|
||||
#include "app/undoers/add_palette.h"
|
||||
#include "app/undoers/dirty_area.h"
|
||||
@ -39,7 +38,6 @@
|
||||
#include "app/undoers/move_layer.h"
|
||||
#include "app/undoers/remove_cel.h"
|
||||
#include "app/undoers/remove_frame.h"
|
||||
#include "app/undoers/remove_image.h"
|
||||
#include "app/undoers/remove_layer.h"
|
||||
#include "app/undoers/remove_palette.h"
|
||||
#include "app/undoers/replace_image.h"
|
||||
@ -73,7 +71,6 @@
|
||||
#include "doc/mask.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "render/quantization.h"
|
||||
#include "render/render.h"
|
||||
|
||||
@ -157,10 +154,6 @@ void DocumentApi::trimSprite(Sprite* sprite)
|
||||
|
||||
void DocumentApi::setPixelFormat(Sprite* sprite, PixelFormat newFormat, DitheringMethod dithering_method)
|
||||
{
|
||||
Image* old_image;
|
||||
Image* new_image;
|
||||
int c;
|
||||
|
||||
if (sprite->pixelFormat() == newFormat)
|
||||
return;
|
||||
|
||||
@ -177,25 +170,23 @@ void DocumentApi::setPixelFormat(Sprite* sprite, PixelFormat newFormat, Ditherin
|
||||
if (sprite->backgroundLayer() != NULL)
|
||||
sprite->backgroundLayer()->getCels(bgCels);
|
||||
|
||||
for (c=0; c<sprite->stock()->size(); c++) {
|
||||
old_image = sprite->stock()->getImage(c);
|
||||
if (!old_image)
|
||||
continue;
|
||||
|
||||
std::vector<Image*> images;
|
||||
sprite->getImages(images);
|
||||
for (auto& old_image : images) {
|
||||
bool is_image_from_background = false;
|
||||
for (CelList::iterator it=bgCels.begin(), end=bgCels.end(); it != end; ++it) {
|
||||
if ((*it)->imageIndex() == c) {
|
||||
if ((*it)->image()->id() == old_image->id()) {
|
||||
is_image_from_background = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
new_image = render::convert_pixel_format
|
||||
ImageRef new_image(render::convert_pixel_format
|
||||
(old_image, NULL, newFormat, dithering_method, rgbmap,
|
||||
sprite->palette(frame),
|
||||
is_image_from_background);
|
||||
sprite->palette(frame),
|
||||
is_image_from_background));
|
||||
|
||||
replaceStockImage(sprite, c, new_image);
|
||||
replaceImage(sprite, sprite->getImage(old_image->id()), new_image);
|
||||
}
|
||||
|
||||
// Set all cels opacity to 100% if we are converting to indexed.
|
||||
@ -310,9 +301,9 @@ void DocumentApi::displaceFrames(Layer* layer, frame_t frame)
|
||||
|
||||
// Add background cel
|
||||
if (imglayer->isBackground()) {
|
||||
Image* bgimage = Image::create(sprite->pixelFormat(), sprite->width(), sprite->height());
|
||||
ImageRef bgimage(Image::create(sprite->pixelFormat(), sprite->width(), sprite->height()));
|
||||
clear_image(bgimage, bgColor(layer));
|
||||
addImage(imglayer, frame, bgimage);
|
||||
addCel(imglayer, frame, bgimage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -583,18 +574,8 @@ void DocumentApi::removeCel(Cel* cel)
|
||||
ev.cel(cel);
|
||||
m_document->notifyObservers<doc::DocumentEvent&>(&doc::DocumentObserver::onRemoveCel, ev);
|
||||
|
||||
// Find if the image that use this cel we are going to remove, is
|
||||
// used by other cels.
|
||||
size_t refs = sprite->getImageRefs(cel->imageIndex());
|
||||
|
||||
// If the image is only used by this cel, we can remove the image
|
||||
// from the stock.
|
||||
if (refs == 1)
|
||||
removeImageFromStock(sprite, cel->imageIndex());
|
||||
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::RemoveCel(getObjects(),
|
||||
layer, cel));
|
||||
m_undoers->pushUndoer(new undoers::RemoveCel(getObjects(), layer, cel));
|
||||
|
||||
// Remove the cel from the layer.
|
||||
layer->removeCel(cel);
|
||||
@ -658,11 +639,11 @@ void DocumentApi::cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h)
|
||||
ASSERT(cel_image);
|
||||
|
||||
// create the new image through a crop
|
||||
Image* new_image = crop_image(cel_image,
|
||||
x-cel->x(), y-cel->y(), w, h, bgColor(cel->layer()));
|
||||
ImageRef new_image(crop_image(cel_image,
|
||||
x-cel->x(), y-cel->y(), w, h, bgColor(cel->layer())));
|
||||
|
||||
// replace the image in the stock that is pointed by the cel
|
||||
replaceStockImage(sprite, cel->imageIndex(), new_image);
|
||||
replaceImage(sprite, cel->imageRef(), new_image);
|
||||
|
||||
// update the cel's position
|
||||
setCelPosition(sprite, cel, x, y);
|
||||
@ -714,7 +695,9 @@ void DocumentApi::moveCel(
|
||||
Cel* srcCel = srcLayer->cel(srcFrame);
|
||||
Cel* dstCel = dstLayer->cel(dstFrame);
|
||||
Image* srcImage = (srcCel ? srcCel->image(): NULL);
|
||||
Image* dstImage = (dstCel ? dstCel->image(): NULL);
|
||||
ImageRef dstImage;
|
||||
if (dstCel)
|
||||
dstImage = dstCel->imageRef();
|
||||
|
||||
if (srcCel) {
|
||||
if (srcLayer == dstLayer) {
|
||||
@ -738,11 +721,11 @@ void DocumentApi::moveCel(
|
||||
// Move the cel between different layers.
|
||||
else {
|
||||
if (!dstCel) {
|
||||
dstImage = Image::createCopy(srcImage);
|
||||
dstImage.reset(Image::createCopy(srcImage));
|
||||
|
||||
dstCel = new Cel(*srcCel);
|
||||
dstCel->setFrame(dstFrame);
|
||||
dstCel->setImage(addImageInStock(dstSprite, dstImage));
|
||||
dstCel->setImage(dstImage);
|
||||
}
|
||||
|
||||
if (dstLayer->isBackground()) {
|
||||
@ -781,7 +764,9 @@ void DocumentApi::copyCel(
|
||||
Cel* srcCel = srcLayer->cel(srcFrame);
|
||||
Cel* dstCel = dstLayer->cel(dstFrame);
|
||||
Image* srcImage = (srcCel ? srcCel->image(): NULL);
|
||||
Image* dstImage = (dstCel ? dstCel->image(): NULL);
|
||||
ImageRef dstImage;
|
||||
if (dstCel)
|
||||
dstImage = dstCel->imageRef();
|
||||
|
||||
if (dstLayer->isBackground()) {
|
||||
if (srcCel) {
|
||||
@ -800,13 +785,12 @@ void DocumentApi::copyCel(
|
||||
removeCel(dstCel);
|
||||
|
||||
if (srcCel) {
|
||||
// Add the image in the stock
|
||||
dstImage = Image::createCopy(srcImage);
|
||||
int imageIndex = addImageInStock(dstSprite, dstImage);
|
||||
// Create a new image in the stock
|
||||
dstImage.reset(Image::createCopy(srcImage));
|
||||
|
||||
dstCel = new Cel(*srcCel);
|
||||
dstCel->setFrame(dstFrame);
|
||||
dstCel->setImage(imageIndex);
|
||||
dstCel->setImage(dstImage);
|
||||
|
||||
addCel(dstLayer, dstCel);
|
||||
}
|
||||
@ -978,10 +962,9 @@ void DocumentApi::backgroundFromLayer(LayerImage* layer)
|
||||
|
||||
// create a temporary image to draw each frame of the new
|
||||
// `Background' layer
|
||||
base::UniquePtr<Image> bg_image_wrap(Image::create(sprite->pixelFormat(),
|
||||
sprite->width(),
|
||||
sprite->height()));
|
||||
Image* bg_image = bg_image_wrap.get();
|
||||
ImageRef bg_image(Image::create(sprite->pixelFormat(),
|
||||
sprite->width(),
|
||||
sprite->height()));
|
||||
|
||||
CelIterator it = layer->getCelBegin();
|
||||
CelIterator end = layer->getCelEnd();
|
||||
@ -1012,7 +995,8 @@ void DocumentApi::backgroundFromLayer(LayerImage* layer)
|
||||
copy_image(cel_image, bg_image, 0, 0);
|
||||
}
|
||||
else {
|
||||
replaceStockImage(sprite, cel->imageIndex(), Image::createCopy(bg_image));
|
||||
ImageRef bg_image2(Image::createCopy(bg_image));
|
||||
replaceImage(sprite, cel->imageRef(), bg_image2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1020,14 +1004,12 @@ void DocumentApi::backgroundFromLayer(LayerImage* layer)
|
||||
for (frame_t frame(0); frame<sprite->totalFrames(); ++frame) {
|
||||
Cel* cel = layer->cel(frame);
|
||||
if (!cel) {
|
||||
Image* cel_image = Image::create(sprite->pixelFormat(), sprite->width(), sprite->height());
|
||||
ImageRef cel_image(Image::create(sprite->pixelFormat(),
|
||||
sprite->width(), sprite->height()));
|
||||
clear_image(cel_image, bgcolor);
|
||||
|
||||
// Add the new image in the stock
|
||||
int image_index = addImageInStock(sprite, cel_image);
|
||||
|
||||
// Create the new cel and add it to the new background layer
|
||||
cel = new Cel(frame, image_index);
|
||||
cel = new Cel(frame, cel_image);
|
||||
addCel(layer, cel);
|
||||
}
|
||||
}
|
||||
@ -1057,7 +1039,7 @@ void DocumentApi::layerFromBackground(Layer* layer)
|
||||
|
||||
void DocumentApi::flattenLayers(Sprite* sprite)
|
||||
{
|
||||
Image* cel_image;
|
||||
ImageRef cel_image;
|
||||
Cel* cel;
|
||||
|
||||
// Create a temporary image.
|
||||
@ -1088,7 +1070,7 @@ void DocumentApi::flattenLayers(Sprite* sprite)
|
||||
|
||||
cel = background->cel(frame);
|
||||
if (cel) {
|
||||
cel_image = cel->image();
|
||||
cel_image = cel->imageRef();
|
||||
ASSERT(cel_image != NULL);
|
||||
|
||||
// We have to save the current state of `cel_image' in the undo.
|
||||
@ -1102,11 +1084,11 @@ void DocumentApi::flattenLayers(Sprite* sprite)
|
||||
else {
|
||||
// If there aren't a cel in this frame in the background, we
|
||||
// have to create a copy of the image for the new cel.
|
||||
cel_image = Image::createCopy(image);
|
||||
cel_image.reset(Image::createCopy(image));
|
||||
// TODO error handling: if createCopy throws
|
||||
|
||||
// Here we create the new cel (with the new image `cel_image').
|
||||
cel = new Cel(frame, sprite->stock()->addImage(cel_image));
|
||||
cel = new Cel(frame, cel_image);
|
||||
// TODO error handling: if new Cel throws
|
||||
|
||||
// And finally we add the cel in the background.
|
||||
@ -1147,30 +1129,11 @@ void DocumentApi::duplicateLayerBefore(Layer* sourceLayer, Layer* beforeLayer)
|
||||
duplicateLayerAfter(sourceLayer, sourceLayer->sprite()->indexToLayer(afterThisIdx));
|
||||
}
|
||||
|
||||
// Adds a new image in the stock. Returns the image index in the
|
||||
// stock.
|
||||
int DocumentApi::addImageInStock(Sprite* sprite, Image* image)
|
||||
Cel* DocumentApi::addCel(LayerImage* layer, frame_t frameNumber, const ImageRef& image)
|
||||
{
|
||||
ASSERT(image != NULL);
|
||||
|
||||
// Do the action.
|
||||
int imageIndex = sprite->stock()->addImage(image);
|
||||
|
||||
// Add undoers.
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::AddImage(getObjects(),
|
||||
sprite->stock(), imageIndex));
|
||||
|
||||
return imageIndex;
|
||||
}
|
||||
|
||||
Cel* DocumentApi::addImage(LayerImage* layer, frame_t frameNumber, Image* image)
|
||||
{
|
||||
int imageIndex = addImageInStock(layer->sprite(), image);
|
||||
|
||||
ASSERT(layer->cel(frameNumber) == NULL);
|
||||
|
||||
base::UniquePtr<Cel> cel(new Cel(frameNumber, imageIndex));
|
||||
base::UniquePtr<Cel> cel(new Cel(frameNumber, image));
|
||||
|
||||
addCel(layer, cel);
|
||||
cel.release();
|
||||
@ -1178,35 +1141,13 @@ Cel* DocumentApi::addImage(LayerImage* layer, frame_t frameNumber, Image* image)
|
||||
return cel;
|
||||
}
|
||||
|
||||
// Removes and destroys the specified image in the stock.
|
||||
void DocumentApi::removeImageFromStock(Sprite* sprite, int imageIndex)
|
||||
void DocumentApi::replaceImage(Sprite* sprite, const ImageRef& oldImage, const ImageRef& newImage)
|
||||
{
|
||||
ASSERT(imageIndex >= 0);
|
||||
|
||||
Image* image = sprite->stock()->getImage(imageIndex);
|
||||
ASSERT(image);
|
||||
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::RemoveImage(getObjects(),
|
||||
sprite->stock(), imageIndex));
|
||||
|
||||
sprite->stock()->removeImage(image);
|
||||
delete image;
|
||||
}
|
||||
|
||||
void DocumentApi::replaceStockImage(Sprite* sprite, int imageIndex, Image* newImage)
|
||||
{
|
||||
// Get the current image in the 'image_index' position.
|
||||
Image* oldImage = sprite->stock()->getImage(imageIndex);
|
||||
ASSERT(oldImage);
|
||||
|
||||
// Replace the image in the stock.
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::ReplaceImage(getObjects(),
|
||||
sprite->stock(), imageIndex));
|
||||
sprite, oldImage, newImage));
|
||||
|
||||
sprite->stock()->replaceImage(imageIndex, newImage);
|
||||
delete oldImage;
|
||||
sprite->replaceImage(oldImage->id(), newImage);
|
||||
}
|
||||
|
||||
void DocumentApi::clearImage(Image* image, color_t bgcolor)
|
||||
|
@ -20,12 +20,13 @@
|
||||
#define APP_DOCUMENT_API_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "gfx/rect.h"
|
||||
#include "doc/algorithm/flip_type.h"
|
||||
#include "doc/color.h"
|
||||
#include "doc/dithering_method.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/pixel_format.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
@ -79,6 +80,7 @@ namespace app {
|
||||
|
||||
// Cels API
|
||||
void addCel(LayerImage* layer, Cel* cel);
|
||||
Cel* addCel(LayerImage* layer, frame_t frameNumber, const ImageRef& image);
|
||||
void clearCel(LayerImage* layer, frame_t frame);
|
||||
void clearCel(Cel* cel);
|
||||
void setCelPosition(Sprite* sprite, Cel* cel, int x, int y);
|
||||
@ -108,11 +110,8 @@ namespace app {
|
||||
void duplicateLayerAfter(Layer* sourceLayer, Layer* afterLayer);
|
||||
void duplicateLayerBefore(Layer* sourceLayer, Layer* beforeLayer);
|
||||
|
||||
// Images stock API
|
||||
Cel* addImage(LayerImage* layer, frame_t frameNumber, Image* image);
|
||||
int addImageInStock(Sprite* sprite, Image* image);
|
||||
void removeImageFromStock(Sprite* sprite, int imageIndex);
|
||||
void replaceStockImage(Sprite* sprite, int imageIndex, Image* newImage);
|
||||
// Images API
|
||||
void replaceImage(Sprite* sprite, const ImageRef& oldImage, const ImageRef& newImage);
|
||||
|
||||
// Image API
|
||||
void clearImage(Image* image, color_t bgcolor);
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "doc/palette.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "gfx/packing_rects.h"
|
||||
#include "gfx/size.h"
|
||||
#include "render/render.h"
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
|
@ -118,13 +118,12 @@ public:
|
||||
|
||||
for (int j=0; j<4; j++) {
|
||||
Cel* cel = layer->cel(frame_t(j));
|
||||
Image* image;
|
||||
ImageRef image;
|
||||
if (cel)
|
||||
image = cel->image();
|
||||
image = cel->imageRef();
|
||||
else {
|
||||
image = Image::create(IMAGE_RGB, 4, 4);
|
||||
int imageIdx = sprite->stock()->addImage(image);
|
||||
cel = new Cel(frame_t(j), imageIdx);
|
||||
image.reset(Image::create(IMAGE_RGB, 4, 4));
|
||||
cel = new Cel(frame_t(j), image);
|
||||
layer->addCel(cel);
|
||||
}
|
||||
|
||||
|
@ -1020,7 +1020,7 @@ static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, frame_t frame,
|
||||
}
|
||||
|
||||
// Create the new frame.
|
||||
base::UniquePtr<Cel> cel(new Cel(frame, 0));
|
||||
base::UniquePtr<Cel> cel(new Cel(frame, ImageRef(NULL)));
|
||||
cel->setPosition(x, y);
|
||||
cel->setOpacity(opacity);
|
||||
|
||||
@ -1032,7 +1032,7 @@ static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, frame_t frame,
|
||||
int h = fgetw(f);
|
||||
|
||||
if (w > 0 && h > 0) {
|
||||
Image* image = Image::create(pixelFormat, w, h);
|
||||
ImageRef image(Image::create(pixelFormat, w, h));
|
||||
|
||||
// Read pixel data
|
||||
switch (image->pixelFormat()) {
|
||||
@ -1050,7 +1050,7 @@ static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, frame_t frame,
|
||||
break;
|
||||
}
|
||||
|
||||
cel->setImage(sprite->stock()->addImage(image));
|
||||
cel->setImage(image);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1061,9 +1061,12 @@ static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, frame_t frame,
|
||||
Cel* link = layer->cel(link_frame);
|
||||
|
||||
if (link) {
|
||||
// Create a copy of the linked cel (avoid using links cel)
|
||||
Image* image = Image::createCopy(link->image());
|
||||
cel->setImage(sprite->stock()->addImage(image));
|
||||
#if 1 // Create a copy of the linked cel (avoid using links cel)
|
||||
ImageRef image(Image::createCopy(link->image()));
|
||||
cel->setImage(image);
|
||||
#else
|
||||
cel->setImage(link->imageRef());
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
// Linked cel doesn't found
|
||||
@ -1078,7 +1081,7 @@ static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, frame_t frame,
|
||||
int h = fgetw(f);
|
||||
|
||||
if (w > 0 && h > 0) {
|
||||
Image* image = Image::create(pixelFormat, w, h);
|
||||
ImageRef image(Image::create(pixelFormat, w, h));
|
||||
|
||||
// Try to read pixel data
|
||||
try {
|
||||
@ -1103,7 +1106,7 @@ static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, frame_t frame,
|
||||
fop_error(fop, e.what());
|
||||
}
|
||||
|
||||
cel->setImage(sprite->stock()->addImage(image));
|
||||
cel->setImage(image);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1120,7 +1123,8 @@ static void ase_file_write_cel_chunk(FILE* f, ASE_FrameHeader* frame_header, Cel
|
||||
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_CEL);
|
||||
|
||||
int layer_index = sprite->layerToIndex(layer);
|
||||
int cel_type = ASE_FILE_COMPRESSED_CEL;
|
||||
Cel* link = cel->link();
|
||||
int cel_type = (link ? ASE_FILE_LINK_CEL: ASE_FILE_COMPRESSED_CEL);
|
||||
|
||||
fputw(layer_index, f);
|
||||
fputw(cel->x(), f);
|
||||
@ -1165,8 +1169,7 @@ static void ase_file_write_cel_chunk(FILE* f, ASE_FrameHeader* frame_header, Cel
|
||||
|
||||
case ASE_FILE_LINK_CEL:
|
||||
// Linked cel to another frame
|
||||
//fputw(link->frame, f);
|
||||
fputw(0, f);
|
||||
fputw(link->frame(), f);
|
||||
break;
|
||||
|
||||
case ASE_FILE_COMPRESSED_CEL: {
|
||||
|
@ -422,7 +422,6 @@ void fop_operate(FileOp *fop, IFileOpProgress* progress)
|
||||
fop->format->support(FILE_SUPPORT_LOAD)) {
|
||||
// Load a sequence
|
||||
if (fop->is_sequence()) {
|
||||
int image_index = 0;
|
||||
Image* old_image;
|
||||
bool loadres;
|
||||
|
||||
@ -432,11 +431,7 @@ void fop_operate(FileOp *fop, IFileOpProgress* progress)
|
||||
// TODO set_palette for each frame???
|
||||
#define SEQUENCE_IMAGE() \
|
||||
do { \
|
||||
image_index = fop->document \
|
||||
->sprite() \
|
||||
->stock()->addImage(fop->seq.image); \
|
||||
\
|
||||
fop->seq.last_cel->setImage(image_index); \
|
||||
fop->seq.last_cel->setImage(fop->seq.image); \
|
||||
fop->seq.layer->addCel(fop->seq.last_cel); \
|
||||
\
|
||||
if (fop->document->sprite()->palette(frame) \
|
||||
@ -446,11 +441,11 @@ void fop_operate(FileOp *fop, IFileOpProgress* progress)
|
||||
} \
|
||||
\
|
||||
old_image = fop->seq.image; \
|
||||
fop->seq.image = NULL; \
|
||||
fop->seq.image.reset(NULL); \
|
||||
fop->seq.last_cel = NULL; \
|
||||
} while (0)
|
||||
|
||||
/* load the sequence */
|
||||
// Load the sequence
|
||||
frame_t frames(fop->seq.filename_list.size());
|
||||
frame_t frame(0);
|
||||
old_image = NULL;
|
||||
@ -556,42 +551,38 @@ void fop_operate(FileOp *fop, IFileOpProgress* progress)
|
||||
Sprite* sprite = fop->document->sprite();
|
||||
|
||||
// Create a temporary bitmap
|
||||
fop->seq.image = Image::create(sprite->pixelFormat(),
|
||||
sprite->width(),
|
||||
sprite->height());
|
||||
if (fop->seq.image != NULL) {
|
||||
fop->seq.progress_offset = 0.0f;
|
||||
fop->seq.progress_fraction = 1.0f / (double)sprite->totalFrames();
|
||||
fop->seq.image.reset(Image::create(sprite->pixelFormat(),
|
||||
sprite->width(),
|
||||
sprite->height()));
|
||||
|
||||
// For each frame in the sprite.
|
||||
render::Render render;
|
||||
for (frame_t frame(0); frame < sprite->totalFrames(); ++frame) {
|
||||
// Draw the "frame" in "fop->seq.image"
|
||||
render.renderSprite(fop->seq.image, sprite, frame);
|
||||
fop->seq.progress_offset = 0.0f;
|
||||
fop->seq.progress_fraction = 1.0f / (double)sprite->totalFrames();
|
||||
|
||||
// Setup the palette.
|
||||
sprite->palette(frame)->copyColorsTo(fop->seq.palette);
|
||||
// For each frame in the sprite.
|
||||
render::Render render;
|
||||
for (frame_t frame(0); frame < sprite->totalFrames(); ++frame) {
|
||||
// Draw the "frame" in "fop->seq.image"
|
||||
render.renderSprite(fop->seq.image, sprite, frame);
|
||||
|
||||
// Setup the filename to be used.
|
||||
fop->filename = fop->seq.filename_list[frame];
|
||||
// Setup the palette.
|
||||
sprite->palette(frame)->copyColorsTo(fop->seq.palette);
|
||||
|
||||
// Call the "save" procedure... did it fail?
|
||||
if (!fop->format->save(fop)) {
|
||||
fop_error(fop, "Error saving frame %d in the file \"%s\"\n",
|
||||
frame+1, fop->filename.c_str());
|
||||
break;
|
||||
}
|
||||
// Setup the filename to be used.
|
||||
fop->filename = fop->seq.filename_list[frame];
|
||||
|
||||
fop->seq.progress_offset += fop->seq.progress_fraction;
|
||||
// Call the "save" procedure... did it fail?
|
||||
if (!fop->format->save(fop)) {
|
||||
fop_error(fop, "Error saving frame %d in the file \"%s\"\n",
|
||||
frame+1, fop->filename.c_str());
|
||||
break;
|
||||
}
|
||||
fop->filename = *fop->seq.filename_list.begin();
|
||||
|
||||
// Destroy the image
|
||||
delete fop->seq.image;
|
||||
}
|
||||
else {
|
||||
fop_error(fop, "Not enough memory for the temporary bitmap.\n");
|
||||
fop->seq.progress_offset += fop->seq.progress_fraction;
|
||||
}
|
||||
fop->filename = *fop->seq.filename_list.begin();
|
||||
|
||||
// Destroy the image
|
||||
fop->seq.image.reset(NULL);
|
||||
}
|
||||
// Direct save to a file.
|
||||
else {
|
||||
@ -741,12 +732,10 @@ Image* fop_sequence_image(FileOp* fop, PixelFormat pixelFormat, int w, int h)
|
||||
}
|
||||
|
||||
// Create a bitmap
|
||||
Image* image = Image::create(pixelFormat, w, h);
|
||||
fop->seq.image.reset(Image::create(pixelFormat, w, h));
|
||||
fop->seq.last_cel = new Cel(fop->seq.frame++, ImageRef(NULL));
|
||||
|
||||
fop->seq.image = image;
|
||||
fop->seq.last_cel = new Cel(fop->seq.frame++, 0);
|
||||
|
||||
return image;
|
||||
return fop->seq.image.get();
|
||||
}
|
||||
|
||||
void fop_error(FileOp *fop, const char *format, ...)
|
||||
@ -831,7 +820,7 @@ static FileOp* fop_new(FileOpType type, Context* context)
|
||||
fop->oneframe = false;
|
||||
|
||||
fop->seq.palette = NULL;
|
||||
fop->seq.image = NULL;
|
||||
fop->seq.image.reset(NULL);
|
||||
fop->seq.progress_offset = 0.0f;
|
||||
fop->seq.progress_fraction = 0.0f;
|
||||
fop->seq.frame = frame_t(0);
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "base/shared_ptr.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/pixel_format.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@ -95,7 +96,7 @@ namespace app {
|
||||
struct {
|
||||
std::vector<std::string> filename_list; // All file names to load/save.
|
||||
Palette* palette; // Palette of the sequence.
|
||||
Image* image; // Image to be saved/loaded.
|
||||
ImageRef image; // Image to be saved/loaded.
|
||||
// For the progress bar.
|
||||
double progress_offset; // Progress offset from the current frame.
|
||||
double progress_fraction; // Progress fraction for one frame.
|
||||
|
@ -133,10 +133,8 @@ bool FliFormat::onLoad(FileOp* fop)
|
||||
++frpos_out;
|
||||
|
||||
// Add the new frame
|
||||
Image* image = Image::createCopy(bmp);
|
||||
index = sprite->stock()->addImage(image);
|
||||
|
||||
Cel* cel = new Cel(frpos_out, index);
|
||||
ImageRef image(Image::createCopy(bmp));
|
||||
Cel* cel = new Cel(frpos_out, image);
|
||||
layer->addCel(cel);
|
||||
|
||||
// First frame or the palette changes
|
||||
|
@ -456,16 +456,15 @@ bool GifFormat::onPostLoad(FileOp* fop)
|
||||
}
|
||||
|
||||
// Create a new Cel and a image with the whole content of "current_image"
|
||||
Cel* cel = new Cel(frame_num, 0);
|
||||
Cel* cel = new Cel(frame_num, ImageRef(0));
|
||||
try {
|
||||
Image* cel_image = Image::createCopy(current_image);
|
||||
ImageRef cel_image(Image::createCopy(current_image));
|
||||
try {
|
||||
// Add the image in the sprite's stock and update the cel's
|
||||
// reference to the new stock's image.
|
||||
cel->setImage(sprite->stock()->addImage(cel_image));
|
||||
cel->setImage(cel_image);
|
||||
}
|
||||
catch (...) {
|
||||
delete cel_image;
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -299,10 +299,9 @@ TEST_F(GifFormat, OpaqueRgbQuantizationTwoLayers)
|
||||
LayerImage* layer2 = new LayerImage(sprite);
|
||||
sprite->folder()->addLayer(layer2);
|
||||
|
||||
Image* image1 = layer1->cel(frame_t(0))->image();
|
||||
Image* image2 = Image::create(IMAGE_RGB, 2, 2);
|
||||
int image2Idx = sprite->stock()->addImage(image2);
|
||||
Cel* cel2 = new Cel(frame_t(0), image2Idx);
|
||||
ImageRef image1 = layer1->cel(frame_t(0))->imageRef();
|
||||
ImageRef image2(Image::create(IMAGE_RGB, 2, 2));
|
||||
Cel* cel2 = new Cel(frame_t(0), image2);
|
||||
layer2->addCel(cel2);
|
||||
|
||||
image1->clear(rgba(255, 255, 255, 255));
|
||||
|
@ -140,9 +140,8 @@ bool IcoFormat::onLoad(FileOp* fop)
|
||||
sprite->folder()->addLayer(layer);
|
||||
|
||||
// Create the first image/cel
|
||||
Image* image = Image::create(pixelFormat, width, height);
|
||||
int image_index = sprite->stock()->addImage(image);
|
||||
Cel* cel = new Cel(frame_t(0), image_index);
|
||||
ImageRef image(Image::create(pixelFormat, width, height));
|
||||
Cel* cel = new Cel(frame_t(0), image);
|
||||
layer->addCel(cel);
|
||||
clear_image(image, 0);
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "render/render.h"
|
||||
|
||||
@ -47,14 +46,10 @@ LayerImage* create_flatten_layer_copy(Sprite* dstSprite, const Layer* srcLayer,
|
||||
// Does this frame have cels to render?
|
||||
if (has_cels(srcLayer, frame)) {
|
||||
// Create a new image to render each frame.
|
||||
base::UniquePtr<Image> imageWrap(Image::create(flatLayer->sprite()->pixelFormat(), bounds.w, bounds.h));
|
||||
|
||||
// Add the image into the sprite's stock too.
|
||||
int imageIndex = flatLayer->sprite()->stock()->addImage(imageWrap);
|
||||
Image* image = imageWrap.release();
|
||||
ImageRef image(Image::create(flatLayer->sprite()->pixelFormat(), bounds.w, bounds.h));
|
||||
|
||||
// Create the new cel for the output layer.
|
||||
base::UniquePtr<Cel> cel(new Cel(frame, imageIndex));
|
||||
base::UniquePtr<Cel> cel(new Cel(frame, image));
|
||||
cel->setPosition(bounds.x, bounds.y);
|
||||
|
||||
// Render this frame.
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "doc/image_bits.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
namespace app {
|
||||
@ -243,12 +242,9 @@ void ColorSelector::onFixWarningClick(ui::Event& ev)
|
||||
if (sprite->pixelFormat() == IMAGE_INDEXED) {
|
||||
lastUsed = sprite->transparentColor();
|
||||
|
||||
Stock* stock = sprite->stock();
|
||||
for (int i=0; i<(int)stock->size(); ++i) {
|
||||
Image* image = stock->getImage(i);
|
||||
if (!image)
|
||||
continue;
|
||||
|
||||
std::vector<Image*> images;
|
||||
sprite->getImages(images);
|
||||
for (Image* image : images) {
|
||||
const LockImageBits<IndexedTraits> bits(image);
|
||||
for (LockImageBits<IndexedTraits>::const_iterator it=bits.begin(); it!=bits.end(); ++it) {
|
||||
if (lastUsed < *it)
|
||||
|
@ -1214,19 +1214,13 @@ void Timeline::drawCel(ui::Graphics* g, LayerIndex layerIndex, frame_t frame, Ce
|
||||
style = m_timelineEmptyFrameStyle;
|
||||
}
|
||||
else {
|
||||
#if 0 // TODO We must find a fast-way to compare keyframes. Cels could
|
||||
// share images until the user draw over them. Also, we could
|
||||
// calculate a hash for each image (and recalculate it when the
|
||||
// user draw over it), so then we can compare hashes. Other
|
||||
// option is to use a thread to calculate differences, but I
|
||||
// think it's too much for just UI stuff.
|
||||
Layer* layer = m_layers[layerIndex];
|
||||
Cel* left = (layer->isImage() ? static_cast<LayerImage*>(layer)->getCel(frame-1): NULL);
|
||||
Cel* right = (layer->isImage() ? static_cast<LayerImage*>(layer)->getCel(frame+1): NULL);
|
||||
Image* leftImg = (left ? m_sprite->stock()->getImage(left->getImage()): NULL);
|
||||
Image* rightImg = (right ? m_sprite->stock()->getImage(right->getImage()): NULL);
|
||||
bool fromLeft = (leftImg && count_diff_between_images(image, leftImg) == 0);
|
||||
bool fromRight = (rightImg && count_diff_between_images(image, rightImg) == 0);
|
||||
Cel* left = (layer->isImage() ? layer->cel(frame-1): NULL);
|
||||
Cel* right = (layer->isImage() ? layer->cel(frame+1): NULL);
|
||||
ObjectId leftImg = (left ? left->image()->id(): 0);
|
||||
ObjectId rightImg = (right ? right->image()->id(): 0);
|
||||
bool fromLeft = (leftImg == cel->image()->id());
|
||||
bool fromRight = (rightImg == cel->image()->id());
|
||||
|
||||
if (fromLeft && fromRight)
|
||||
style = m_timelineFromBothStyle;
|
||||
@ -1235,7 +1229,6 @@ void Timeline::drawCel(ui::Graphics* g, LayerIndex layerIndex, frame_t frame, Ce
|
||||
else if (fromRight)
|
||||
style = m_timelineFromRightStyle;
|
||||
else
|
||||
#endif
|
||||
style = m_timelineKeyframeStyle;
|
||||
}
|
||||
drawPart(g, bounds, NULL, style, is_active, is_hover);
|
||||
|
@ -1,63 +0,0 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/undoers/add_image.h"
|
||||
|
||||
#include "app/undoers/remove_image.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/stock.h"
|
||||
#include "undo/objects_container.h"
|
||||
#include "undo/undo_exception.h"
|
||||
#include "undo/undoers_collector.h"
|
||||
|
||||
namespace app {
|
||||
namespace undoers {
|
||||
|
||||
using namespace undo;
|
||||
|
||||
AddImage::AddImage(ObjectsContainer* objects, Stock* stock, int imageIndex)
|
||||
: m_stockId(objects->addObject(stock))
|
||||
, m_imageIndex(imageIndex)
|
||||
{
|
||||
}
|
||||
|
||||
void AddImage::dispose()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void AddImage::revert(ObjectsContainer* objects, UndoersCollector* redoers)
|
||||
{
|
||||
Stock* stock = objects->getObjectT<Stock>(m_stockId);
|
||||
Image* image = stock->getImage(m_imageIndex);
|
||||
|
||||
if (image == NULL)
|
||||
throw UndoException("One image was not found in the stock");
|
||||
|
||||
redoers->pushUndoer(new RemoveImage(objects, stock, m_imageIndex));
|
||||
|
||||
stock->removeImage(image);
|
||||
delete image;
|
||||
}
|
||||
|
||||
} // namespace undoers
|
||||
} // namespace app
|
@ -1,51 +0,0 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef APP_UNDOERS_ADD_IMAGE_H_INCLUDED
|
||||
#define APP_UNDOERS_ADD_IMAGE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/undoers/undoer_base.h"
|
||||
#include "undo/object_id.h"
|
||||
|
||||
namespace doc {
|
||||
class Stock;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
namespace undoers {
|
||||
using namespace doc;
|
||||
using namespace undo;
|
||||
|
||||
class AddImage : public UndoerBase {
|
||||
public:
|
||||
AddImage(ObjectsContainer* objects, Stock* stock, int imageIndex);
|
||||
|
||||
void dispose() override;
|
||||
size_t getMemSize() const override { return sizeof(*this); }
|
||||
void revert(ObjectsContainer* objects, UndoersCollector* redoers) override;
|
||||
|
||||
private:
|
||||
undo::ObjectId m_stockId;
|
||||
uint32_t m_imageIndex;
|
||||
};
|
||||
|
||||
} // namespace undoers
|
||||
} // namespace app
|
||||
|
||||
#endif // UNDOERS_ADD_IMAGE_H_INCLUDED
|
86
src/app/undoers/object_io.cpp
Normal file
86
src/app/undoers/object_io.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/undoers/object_io.h"
|
||||
|
||||
#include "doc/cel.h"
|
||||
#include "doc/cel_io.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/layer_io.h"
|
||||
|
||||
namespace app {
|
||||
namespace undoers {
|
||||
|
||||
using namespace undo;
|
||||
|
||||
ObjectIO::ObjectIO(ObjectsContainer* objects, Sprite* sprite)
|
||||
: m_objects(objects)
|
||||
, m_sprite(sprite)
|
||||
{
|
||||
}
|
||||
|
||||
ObjectIO::~ObjectIO()
|
||||
{
|
||||
}
|
||||
|
||||
void ObjectIO::write_cel(std::ostream& os, Cel* cel)
|
||||
{
|
||||
write_object(os, cel, [this](std::ostream& os, Cel* cel) {
|
||||
doc::write_cel(os, this, cel);
|
||||
});
|
||||
}
|
||||
|
||||
void ObjectIO::write_image(std::ostream& os, Image* image)
|
||||
{
|
||||
write_object(os, image, doc::write_image);
|
||||
}
|
||||
|
||||
void ObjectIO::write_layer(std::ostream& os, Layer* layer)
|
||||
{
|
||||
write_object(os, layer, [this](std::ostream& os, Layer* layer) {
|
||||
doc::write_layer(os, this, layer);
|
||||
});
|
||||
}
|
||||
|
||||
Cel* ObjectIO::read_cel(std::istream& is)
|
||||
{
|
||||
return read_object<Cel>(is, [this](std::istream& is) {
|
||||
return doc::read_cel(is, this, m_sprite);
|
||||
});
|
||||
}
|
||||
|
||||
Image* ObjectIO::read_image(std::istream& is)
|
||||
{
|
||||
return read_object<Image>(is, doc::read_image);
|
||||
}
|
||||
|
||||
Layer* ObjectIO::read_layer(std::istream& is)
|
||||
{
|
||||
return read_object<Layer>(is, [this](std::istream& is) {
|
||||
return doc::read_layer(is, this, m_sprite);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace undoers
|
||||
} // namespace app
|
@ -22,10 +22,37 @@
|
||||
|
||||
#include "base/serialization.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "doc/subobjects_io.h"
|
||||
#include "undo/objects_container.h"
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
class Image;
|
||||
class Layer;
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
namespace undoers {
|
||||
namespace undoers {
|
||||
using namespace doc;
|
||||
using namespace undo;
|
||||
|
||||
class ObjectIO : public SubObjectsIO {
|
||||
public:
|
||||
ObjectIO(ObjectsContainer* objects, Sprite* sprite);
|
||||
virtual ~ObjectIO();
|
||||
|
||||
// How to write cels, images, and sub-layers
|
||||
void write_cel(std::ostream& os, Cel* cel) override;
|
||||
void write_image(std::ostream& os, Image* image) override;
|
||||
void write_layer(std::ostream& os, Layer* layer) override;
|
||||
|
||||
// How to read cels, images, and sub-layers
|
||||
Cel* read_cel(std::istream& is) override;
|
||||
Image* read_image(std::istream& is) override;
|
||||
Layer* read_layer(std::istream& is) override;
|
||||
|
||||
private:
|
||||
|
||||
// read_object and write_object functions can be used to serialize an
|
||||
// object into a stream, and restore it back into the memory with the
|
||||
@ -35,37 +62,41 @@ namespace app {
|
||||
// ID from the ObjectsContainer. When the object is deserialized with
|
||||
// read_object, the object is added to the container with the same ID.
|
||||
template<class T, class Writer>
|
||||
void write_object(undo::ObjectsContainer* objects, std::ostream& os, T* object, Writer& writer)
|
||||
void write_object(std::ostream& os, T* object, Writer writer)
|
||||
{
|
||||
using base::serialization::little_endian::write32;
|
||||
|
||||
// Get an ID for the image.
|
||||
undo::ObjectId objectId = objects->addObject(object);
|
||||
undo::ObjectId objectId = m_objects->addObject(object);
|
||||
|
||||
write32(os, objectId); // Write the ID
|
||||
writer(os, object); // Write the object
|
||||
|
||||
// Remove the object from the container (it will be
|
||||
// re-added by a undoers::read_object call).
|
||||
objects->removeObject(objectId);
|
||||
m_objects->removeObject(objectId);
|
||||
}
|
||||
|
||||
// Deserializes the given object from the stream, adding the object
|
||||
// into the ObjectsContainer with the same ID saved with write_object().
|
||||
template<class T, class Reader>
|
||||
T* read_object(undo::ObjectsContainer* objects, std::istream& is, Reader& reader)
|
||||
T* read_object(std::istream& is, Reader reader)
|
||||
{
|
||||
using base::serialization::little_endian::read32;
|
||||
|
||||
undo::ObjectId objectId = read32(is); // Read the ID
|
||||
base::UniquePtr<T> object(reader(is)); // Read the object
|
||||
base::UniquePtr<T> object(reader(is)); // Read the object
|
||||
|
||||
// Re-insert the object in the container with the read ID.
|
||||
objects->insertObject(objectId, object);
|
||||
m_objects->insertObject(objectId, object);
|
||||
return object.release();
|
||||
}
|
||||
|
||||
} // namespace undoers
|
||||
ObjectsContainer* m_objects;
|
||||
Sprite* m_sprite;
|
||||
};
|
||||
|
||||
} // namespace undoers
|
||||
} // namespace app
|
||||
|
||||
#endif // UNDOERS_OBJECT_IO_H_INCLUDED
|
||||
|
@ -25,9 +25,7 @@
|
||||
#include "app/undoers/add_cel.h"
|
||||
#include "app/undoers/object_io.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/cel_io.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/stock.h"
|
||||
#include "undo/objects_container.h"
|
||||
#include "undo/undoers_collector.h"
|
||||
|
||||
@ -40,7 +38,7 @@ using namespace undo;
|
||||
RemoveCel::RemoveCel(ObjectsContainer* objects, Layer* layer, Cel* cel)
|
||||
: m_layerId(objects->addObject(layer))
|
||||
{
|
||||
write_object(objects, m_stream, cel, doc::write_cel);
|
||||
ObjectIO(objects, layer->sprite()).write_cel(m_stream, cel);
|
||||
}
|
||||
|
||||
void RemoveCel::dispose()
|
||||
@ -51,9 +49,8 @@ void RemoveCel::dispose()
|
||||
void RemoveCel::revert(ObjectsContainer* objects, UndoersCollector* redoers)
|
||||
{
|
||||
LayerImage* layer = objects->getObjectT<LayerImage>(m_layerId);
|
||||
Cel* cel = read_object<Cel>(objects, m_stream, doc::read_cel);
|
||||
Cel* cel = ObjectIO(objects, layer->sprite()).read_cel(m_stream);
|
||||
|
||||
// Push an AddCel as redoer
|
||||
redoers->pushUndoer(new AddCel(objects, layer, cel));
|
||||
|
||||
layer->addCel(cel);
|
||||
|
@ -1,65 +0,0 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/undoers/remove_image.h"
|
||||
|
||||
#include "app/undoers/add_image.h"
|
||||
#include "app/undoers/object_io.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/stock.h"
|
||||
#include "undo/objects_container.h"
|
||||
#include "undo/undoers_collector.h"
|
||||
|
||||
namespace app {
|
||||
namespace undoers {
|
||||
|
||||
using namespace doc;
|
||||
using namespace undo;
|
||||
|
||||
RemoveImage::RemoveImage(ObjectsContainer* objects, Stock* stock, int imageIndex)
|
||||
: m_stockId(objects->addObject(stock))
|
||||
, m_imageIndex(imageIndex)
|
||||
{
|
||||
Image* image = stock->getImage(imageIndex);
|
||||
|
||||
write_object(objects, m_stream, image, doc::write_image);
|
||||
}
|
||||
|
||||
void RemoveImage::dispose()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void RemoveImage::revert(ObjectsContainer* objects, UndoersCollector* redoers)
|
||||
{
|
||||
Stock* stock = objects->getObjectT<Stock>(m_stockId);
|
||||
Image* image = read_object<Image>(objects, m_stream, doc::read_image);
|
||||
|
||||
// Push an AddImage as redoer
|
||||
redoers->pushUndoer(new AddImage(objects, stock, m_imageIndex));
|
||||
|
||||
stock->replaceImage(m_imageIndex, image);
|
||||
}
|
||||
|
||||
} // namespace undoers
|
||||
} // namespace app
|
@ -1,58 +0,0 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef APP_UNDOERS_REMOVE_IMAGE_H_INCLUDED
|
||||
#define APP_UNDOERS_REMOVE_IMAGE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/undoers/undoer_base.h"
|
||||
#include "undo/object_id.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace doc {
|
||||
class Stock;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
namespace undoers {
|
||||
using namespace doc;
|
||||
using namespace undo;
|
||||
|
||||
class RemoveImage : public UndoerBase {
|
||||
public:
|
||||
RemoveImage(ObjectsContainer* objects, Stock* stock, int imageIndex);
|
||||
|
||||
void dispose() override;
|
||||
size_t getMemSize() const override { return sizeof(*this) + getStreamSize(); }
|
||||
void revert(ObjectsContainer* objects, UndoersCollector* redoers) override;
|
||||
|
||||
private:
|
||||
size_t getStreamSize() const {
|
||||
return const_cast<std::stringstream*>(&m_stream)->tellp();
|
||||
}
|
||||
|
||||
undo::ObjectId m_stockId;
|
||||
uint32_t m_imageIndex;
|
||||
std::stringstream m_stream;
|
||||
};
|
||||
|
||||
} // namespace undoers
|
||||
} // namespace app
|
||||
|
||||
#endif // UNDOERS_REMOVE_IMAGE_H_INCLUDED
|
@ -27,11 +27,8 @@
|
||||
#include "app/undoers/add_layer.h"
|
||||
#include "app/undoers/object_io.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/cel_io.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/layer_io.h"
|
||||
#include "undo/objects_container.h"
|
||||
#include "undo/undoers_collector.h"
|
||||
|
||||
@ -40,58 +37,6 @@ namespace undoers {
|
||||
|
||||
using namespace undo;
|
||||
|
||||
class LayerSubObjectsSerializerImpl : public doc::LayerSubObjectsSerializer {
|
||||
public:
|
||||
LayerSubObjectsSerializerImpl(ObjectsContainer* objects, Sprite* sprite)
|
||||
: m_objects(objects)
|
||||
, m_sprite(sprite) {
|
||||
}
|
||||
|
||||
virtual ~LayerSubObjectsSerializerImpl() { }
|
||||
|
||||
// How to write cels, images, and sub-layers
|
||||
void write_cel(std::ostream& os, Cel* cel) override {
|
||||
write_object(m_objects, os, cel, doc::write_cel);
|
||||
}
|
||||
|
||||
void write_image(std::ostream& os, Image* image) override {
|
||||
write_object(m_objects, os, image, doc::write_image);
|
||||
}
|
||||
|
||||
void write_layer(std::ostream& os, Layer* layer) override {
|
||||
// To write a sub-layer we use the operator() of this instance (*this)
|
||||
write_object(m_objects, os, layer, *this);
|
||||
}
|
||||
|
||||
// How to read cels, images, and sub-layers
|
||||
Cel* read_cel(std::istream& is) override {
|
||||
return read_object<Cel>(m_objects, is, doc::read_cel);
|
||||
}
|
||||
|
||||
Image* read_image(std::istream& is) override {
|
||||
return read_object<Image>(m_objects, is, doc::read_image);
|
||||
}
|
||||
|
||||
Layer* read_layer(std::istream& is) override {
|
||||
// To read a sub-layer we use the operator() of this instance (*this)
|
||||
return read_object<Layer>(m_objects, is, *this);
|
||||
}
|
||||
|
||||
// The following operator() calls are used in write/read_object() functions.
|
||||
|
||||
void operator()(std::ostream& os, Layer* layer) {
|
||||
doc::write_layer(os, this, layer);
|
||||
}
|
||||
|
||||
Layer* operator()(std::istream& is) {
|
||||
return doc::read_layer(is, this, m_sprite);
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectsContainer* m_objects;
|
||||
Sprite* m_sprite;
|
||||
};
|
||||
|
||||
RemoveLayer::RemoveLayer(ObjectsContainer* objects, Document* document, Layer* layer)
|
||||
: m_documentId(objects->addObject(document))
|
||||
, m_folderId(objects->addObject(layer->parent()))
|
||||
@ -99,8 +44,7 @@ RemoveLayer::RemoveLayer(ObjectsContainer* objects, Document* document, Layer* l
|
||||
Layer* after = layer->getPrevious();
|
||||
m_afterId = (after ? objects->addObject(after): 0);
|
||||
|
||||
LayerSubObjectsSerializerImpl serializer(objects, layer->sprite());
|
||||
write_object(objects, m_stream, layer, serializer);
|
||||
ObjectIO(objects, layer->sprite()).write_layer(m_stream, layer);
|
||||
}
|
||||
|
||||
void RemoveLayer::dispose()
|
||||
@ -115,8 +59,8 @@ void RemoveLayer::revert(ObjectsContainer* objects, UndoersCollector* redoers)
|
||||
Layer* after = (m_afterId != 0 ? objects->getObjectT<Layer>(m_afterId): NULL);
|
||||
|
||||
// Read the layer from the stream
|
||||
LayerSubObjectsSerializerImpl serializer(objects, folder->sprite());
|
||||
Layer* layer = read_object<Layer>(objects, m_stream, serializer);
|
||||
Layer* layer =
|
||||
ObjectIO(objects, folder->sprite()).read_layer(m_stream);
|
||||
|
||||
document->getApi(redoers).addLayer(folder, layer, after);
|
||||
}
|
||||
|
@ -25,7 +25,8 @@
|
||||
#include "app/undoers/object_io.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/image_io.h"
|
||||
#include "doc/stock.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "undo/objects_container.h"
|
||||
#include "undo/undoers_collector.h"
|
||||
|
||||
@ -34,13 +35,12 @@ namespace undoers {
|
||||
|
||||
using namespace undo;
|
||||
|
||||
ReplaceImage::ReplaceImage(ObjectsContainer* objects, Stock* stock, int imageIndex)
|
||||
: m_stockId(objects->addObject(stock))
|
||||
, m_imageIndex(imageIndex)
|
||||
ReplaceImage::ReplaceImage(ObjectsContainer* objects, Sprite* sprite,
|
||||
Image* oldImage, Image* newImage)
|
||||
: m_spriteId(objects->addObject(sprite))
|
||||
, m_newImageId(objects->addObject(newImage))
|
||||
{
|
||||
Image* image = stock->getImage(imageIndex);
|
||||
|
||||
write_object(objects, m_stream, image, doc::write_image);
|
||||
ObjectIO(objects, sprite).write_image(m_stream, oldImage);
|
||||
}
|
||||
|
||||
void ReplaceImage::dispose()
|
||||
@ -50,20 +50,23 @@ void ReplaceImage::dispose()
|
||||
|
||||
void ReplaceImage::revert(ObjectsContainer* objects, UndoersCollector* redoers)
|
||||
{
|
||||
Stock* stock = objects->getObjectT<Stock>(m_stockId);
|
||||
Sprite* sprite = objects->getObjectT<Sprite>(m_spriteId);
|
||||
Image* currentImageRaw = objects->getObjectT<Image>(m_newImageId);
|
||||
ASSERT(currentImageRaw != NULL);
|
||||
|
||||
ImageRef currentImage = sprite->getImage(currentImageRaw->id());
|
||||
ASSERT(currentImage != NULL);
|
||||
|
||||
// Read the image to be restored from the stream
|
||||
Image* image = read_object<Image>(objects, m_stream, doc::read_image);
|
||||
ImageRef restoreImage(
|
||||
ObjectIO(objects, sprite).read_image(m_stream));
|
||||
|
||||
// Save the current image in the redoers
|
||||
redoers->pushUndoer(new ReplaceImage(objects, stock, m_imageIndex));
|
||||
Image* oldImage = stock->getImage(m_imageIndex);
|
||||
redoers->pushUndoer(new ReplaceImage(objects, sprite,
|
||||
currentImage, restoreImage));
|
||||
|
||||
// Replace the image in the stock
|
||||
stock->replaceImage(m_imageIndex, image);
|
||||
|
||||
// Destroy the old image
|
||||
delete oldImage;
|
||||
sprite->replaceImage(currentImage->id(), restoreImage);
|
||||
}
|
||||
|
||||
} // namespace undoers
|
||||
|
@ -26,7 +26,8 @@
|
||||
#include <sstream>
|
||||
|
||||
namespace doc {
|
||||
class Stock;
|
||||
class Image;
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
@ -36,7 +37,8 @@ namespace app {
|
||||
|
||||
class ReplaceImage : public UndoerBase {
|
||||
public:
|
||||
ReplaceImage(ObjectsContainer* objects, Stock* stock, int imageIndex);
|
||||
ReplaceImage(ObjectsContainer* objects, Sprite* sprite,
|
||||
Image* oldImage, Image* newImage);
|
||||
|
||||
void dispose() override;
|
||||
size_t getMemSize() const override { return sizeof(*this) + getStreamSize(); }
|
||||
@ -47,8 +49,8 @@ namespace app {
|
||||
return const_cast<std::stringstream*>(&m_stream)->tellp();
|
||||
}
|
||||
|
||||
undo::ObjectId m_stockId;
|
||||
uint32_t m_imageIndex;
|
||||
undo::ObjectId m_spriteId;
|
||||
undo::ObjectId m_newImageId;
|
||||
std::stringstream m_stream;
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include "app/ui/timeline.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/undo_transaction.h"
|
||||
#include "app/undoers/add_image.h"
|
||||
#include "app/undoers/image_area.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "app/util/misc.h"
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "app/document_location.h"
|
||||
#include "app/undo_transaction.h"
|
||||
#include "app/undoers/add_cel.h"
|
||||
#include "app/undoers/add_image.h"
|
||||
#include "app/undoers/dirty_area.h"
|
||||
#include "app/undoers/modified_region.h"
|
||||
#include "app/undoers/replace_image.h"
|
||||
@ -40,7 +39,6 @@
|
||||
#include "doc/layer.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -88,14 +86,14 @@ ExpandCelCanvas::ExpandCelCanvas(Context* context, TiledMode tiledMode, UndoTran
|
||||
if (m_layer->isImage()) {
|
||||
m_cel = m_layer->cel(location.frame());
|
||||
if (m_cel)
|
||||
m_celImage = m_cel->image();
|
||||
m_celImage = m_cel->imageRef();
|
||||
}
|
||||
|
||||
// If there is no Cel
|
||||
if (m_cel == NULL) {
|
||||
// Create the cel
|
||||
m_celCreated = true;
|
||||
m_cel = new Cel(location.frame(), 0);
|
||||
m_cel = new Cel(location.frame(), ImageRef(NULL));
|
||||
static_cast<LayerImage*>(m_layer)->addCel(m_cel);
|
||||
}
|
||||
|
||||
@ -152,25 +150,21 @@ void ExpandCelCanvas::commit()
|
||||
// don't have a m_celImage)
|
||||
validateDestCanvas(gfx::Region(m_bounds));
|
||||
|
||||
// We can temporary remove the cel.
|
||||
static_cast<LayerImage*>(m_layer)->removeCel(m_cel);
|
||||
|
||||
// Add a copy of m_dstImage in the sprite's image stock
|
||||
m_cel->setImage(m_sprite->stock()->addImage(
|
||||
Image::createCopy(m_dstImage)));
|
||||
ImageRef newImage(Image::createCopy(m_dstImage));
|
||||
m_cel->setImage(newImage);
|
||||
|
||||
// Is the undo enabled?.
|
||||
if (m_undo.isEnabled()) {
|
||||
// We can temporary remove the cel.
|
||||
static_cast<LayerImage*>(m_layer)->removeCel(m_cel);
|
||||
|
||||
// We create the undo information (for the new m_celImage
|
||||
// in the stock and the new cel in the layer)...
|
||||
m_undo.pushUndoer(new undoers::AddImage(m_undo.getObjects(),
|
||||
m_sprite->stock(), m_cel->imageIndex()));
|
||||
m_undo.pushUndoer(new undoers::AddCel(m_undo.getObjects(),
|
||||
m_layer, m_cel));
|
||||
|
||||
// And finally we add the cel again in the layer.
|
||||
static_cast<LayerImage*>(m_layer)->addCel(m_cel);
|
||||
}
|
||||
|
||||
// And finally we add the cel again in the layer.
|
||||
static_cast<LayerImage*>(m_layer)->addCel(m_cel);
|
||||
}
|
||||
else if (m_celImage) {
|
||||
// If the size of each image is the same, we can create an undo
|
||||
@ -206,9 +200,6 @@ void ExpandCelCanvas::commit()
|
||||
m_undo.pushUndoer(new undoers::SetCelPosition(m_undo.getObjects(), m_cel));
|
||||
m_cel->setPosition(newPos);
|
||||
}
|
||||
|
||||
m_undo.pushUndoer(new undoers::ReplaceImage(m_undo.getObjects(),
|
||||
m_sprite->stock(), m_cel->imageIndex()));
|
||||
}
|
||||
|
||||
// Validate the whole m_dstImage copying invalid areas from m_celImage
|
||||
@ -216,11 +207,13 @@ void ExpandCelCanvas::commit()
|
||||
|
||||
// Replace the image in the stock. We need to create a copy of
|
||||
// image because m_dstImage's ImageBuffer cannot be shared.
|
||||
m_sprite->stock()->replaceImage(m_cel->imageIndex(),
|
||||
Image::createCopy(m_dstImage));
|
||||
ImageRef newImage(Image::createCopy(m_dstImage));
|
||||
|
||||
// Destroy the old cel image.
|
||||
delete m_celImage;
|
||||
if (m_undo.isEnabled())
|
||||
m_undo.pushUndoer(new undoers::ReplaceImage(m_undo.getObjects(),
|
||||
m_sprite, m_celImage, newImage));
|
||||
|
||||
m_sprite->replaceImage(m_celImage->id(), newImage);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -241,7 +234,7 @@ void ExpandCelCanvas::rollback()
|
||||
if (m_celCreated) {
|
||||
static_cast<LayerImage*>(m_layer)->removeCel(m_cel);
|
||||
delete m_cel;
|
||||
delete m_celImage;
|
||||
m_celImage.reset(NULL);
|
||||
}
|
||||
|
||||
m_closed = true;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define APP_UTIL_EXPAND_CEL_CANVAS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/image_ref.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
@ -85,7 +86,7 @@ namespace app {
|
||||
Sprite* m_sprite;
|
||||
Layer* m_layer;
|
||||
Cel* m_cel;
|
||||
Image* m_celImage;
|
||||
ImageRef m_celImage;
|
||||
bool m_celCreated;
|
||||
gfx::Point m_origCelPos;
|
||||
gfx::Point m_celPos;
|
||||
|
@ -38,5 +38,4 @@ add_library(doc-lib
|
||||
primitives.cpp
|
||||
rgbmap.cpp
|
||||
sprite.cpp
|
||||
sprites.cpp
|
||||
stock.cpp)
|
||||
sprites.cpp)
|
||||
|
@ -14,11 +14,10 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
namespace doc {
|
||||
|
||||
Cel::Cel(frame_t frame, int image)
|
||||
Cel::Cel(frame_t frame, const ImageRef& image)
|
||||
: Object(ObjectType::Cel)
|
||||
, m_layer(NULL)
|
||||
, m_frame(frame)
|
||||
@ -42,26 +41,16 @@ Cel::~Cel()
|
||||
{
|
||||
}
|
||||
|
||||
Image* Cel::image() const
|
||||
void Cel::setFrame(frame_t frame)
|
||||
{
|
||||
ASSERT(m_layer != NULL);
|
||||
ASSERT(m_image >= 0);
|
||||
ASSERT(m_image < m_layer->sprite()->stock()->size());
|
||||
ASSERT(m_layer == NULL);
|
||||
m_frame = frame;
|
||||
}
|
||||
|
||||
if (m_layer) {
|
||||
Stock* stock = m_layer->sprite()->stock();
|
||||
|
||||
ASSERT(stock);
|
||||
ASSERT(m_image >= 0 && m_image < stock->size());
|
||||
|
||||
if (m_image >= 0 && m_image < stock->size()) {
|
||||
Image* image = stock->getImage(m_image);
|
||||
ASSERT((m_image == 0 && !image) || (m_image != 0 && image));
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
void Cel::setImage(const ImageRef& image)
|
||||
{
|
||||
m_image = image;
|
||||
fixupImage();
|
||||
}
|
||||
|
||||
Sprite* Cel::sprite() const
|
||||
@ -73,6 +62,22 @@ Sprite* Cel::sprite() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Cel* Cel::link() const
|
||||
{
|
||||
if (m_image.get() == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!m_image.unique()) {
|
||||
for (frame_t fr=0; fr<m_frame; ++fr) {
|
||||
Cel* possible = m_layer->cel(fr);
|
||||
if (possible && possible->imageRef().get() == m_image.get())
|
||||
return possible;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gfx::Rect Cel::bounds() const
|
||||
{
|
||||
Image* image = this->image();
|
||||
@ -85,4 +90,17 @@ gfx::Rect Cel::bounds() const
|
||||
return gfx::Rect();
|
||||
}
|
||||
|
||||
void Cel::setParentLayer(LayerImage* layer)
|
||||
{
|
||||
m_layer = layer;
|
||||
fixupImage();
|
||||
}
|
||||
|
||||
void Cel::fixupImage()
|
||||
{
|
||||
// Change the mask color to the sprite mask color
|
||||
if (m_layer && m_image.get())
|
||||
m_image->setMaskColor(m_layer->sprite()->transparentColor());
|
||||
}
|
||||
|
||||
} // namespace doc
|
||||
|
@ -9,39 +9,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "doc/frame.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/object.h"
|
||||
#include "gfx/fwd.h"
|
||||
#include "gfx/point.h"
|
||||
|
||||
namespace doc {
|
||||
|
||||
class Image;
|
||||
class LayerImage;
|
||||
class Sprite;
|
||||
|
||||
class Cel : public Object {
|
||||
public:
|
||||
Cel(frame_t frame, int image);
|
||||
Cel(frame_t frame, const ImageRef& image);
|
||||
Cel(const Cel& cel);
|
||||
virtual ~Cel();
|
||||
|
||||
frame_t frame() const { return m_frame; }
|
||||
int imageIndex() const { return m_image; }
|
||||
int x() const { return m_position.x; }
|
||||
int y() const { return m_position.y; }
|
||||
gfx::Point position() const { return m_position; }
|
||||
int opacity() const { return m_opacity; }
|
||||
|
||||
LayerImage* layer() const { return m_layer; }
|
||||
Image* image() const;
|
||||
Image* image() const { return const_cast<Image*>(m_image.get()); };
|
||||
ImageRef imageRef() const { return m_image; }
|
||||
Sprite* sprite() const;
|
||||
Cel* link() const;
|
||||
gfx::Rect bounds() const;
|
||||
|
||||
// You should change the frame only if the cel isn't member of a
|
||||
// layer. If the cel is already in a layer, you should use
|
||||
// LayerImage::moveCel() member function.
|
||||
void setFrame(frame_t frame) { m_frame = frame; }
|
||||
void setImage(int image) { m_image = image; }
|
||||
void setFrame(frame_t frame);
|
||||
void setImage(const ImageRef& image);
|
||||
void setPosition(int x, int y) {
|
||||
m_position.x = x;
|
||||
m_position.y = y;
|
||||
@ -53,14 +54,14 @@ namespace doc {
|
||||
return sizeof(Cel);
|
||||
}
|
||||
|
||||
void setParentLayer(LayerImage* layer) {
|
||||
m_layer = layer;
|
||||
}
|
||||
void setParentLayer(LayerImage* layer);
|
||||
|
||||
private:
|
||||
void fixupImage();
|
||||
|
||||
LayerImage* m_layer;
|
||||
frame_t m_frame; // Frame position
|
||||
int m_image; // Image index of stock
|
||||
ImageRef m_image;
|
||||
gfx::Point m_position; // X/Y screen position
|
||||
int m_opacity; // Opacity level
|
||||
};
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "base/serialization.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/subobjects_io.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -21,43 +23,41 @@ namespace doc {
|
||||
using namespace base::serialization;
|
||||
using namespace base::serialization::little_endian;
|
||||
|
||||
// Serialized Cel data:
|
||||
//
|
||||
// WORD Frame
|
||||
// WORD Image index
|
||||
// WORD[2] X, Y
|
||||
// WORD Opacity
|
||||
|
||||
void write_cel(std::ostream& os, Cel* cel)
|
||||
void write_cel(std::ostream& os, SubObjectsIO* subObjects, Cel* cel)
|
||||
{
|
||||
// ObjectId cel_id = objects->addObject(cel);
|
||||
// write_raw_uint32(cel_id);
|
||||
Cel* link = cel->link();
|
||||
|
||||
write16(os, cel->frame());
|
||||
write16(os, cel->imageIndex());
|
||||
write16(os, (int16_t)cel->x());
|
||||
write16(os, (int16_t)cel->y());
|
||||
write16(os, cel->opacity());
|
||||
|
||||
// objects->removeObject(cel_id);
|
||||
write16(os, link ? 1: 0);
|
||||
if (link)
|
||||
write32(os, link->id());
|
||||
else
|
||||
subObjects->write_image(os, cel->image());
|
||||
}
|
||||
|
||||
Cel* read_cel(std::istream& is)
|
||||
Cel* read_cel(std::istream& is, SubObjectsIO* subObjects, Sprite* sprite)
|
||||
{
|
||||
// ObjectId cel_id = read32();
|
||||
|
||||
frame_t frame(read16(is));
|
||||
int imageIndex = read16(is);
|
||||
int x = (int16_t)read16(is);
|
||||
int y = (int16_t)read16(is);
|
||||
int opacity = read16(is);
|
||||
bool is_link = (read16(is) == 1);
|
||||
|
||||
base::UniquePtr<Cel> cel(new Cel(frame, imageIndex));
|
||||
base::UniquePtr<Cel> cel(new Cel(frame, ImageRef(NULL)));
|
||||
|
||||
cel->setPosition(x, y);
|
||||
cel->setOpacity(opacity);
|
||||
|
||||
// objects->insertObject(cel_id, cel);
|
||||
if (is_link) {
|
||||
ObjectId imageId = read32(is);
|
||||
cel->setImage(sprite->getImage(imageId));
|
||||
}
|
||||
else
|
||||
cel->setImage(ImageRef(subObjects->read_image(is)));
|
||||
|
||||
return cel.release();
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,11 @@
|
||||
namespace doc {
|
||||
|
||||
class Cel;
|
||||
class Sprite;
|
||||
class SubObjectsIO;
|
||||
|
||||
void write_cel(std::ostream& os, Cel* cel);
|
||||
Cel* read_cel(std::istream& is);
|
||||
void write_cel(std::ostream& os, SubObjectsIO* subObjects, Cel* cel);
|
||||
Cel* read_cel(std::istream& is, SubObjectsIO* subObjects, Sprite* sprite);
|
||||
|
||||
} // namespace doc
|
||||
|
||||
|
@ -27,6 +27,5 @@
|
||||
#include "doc/primitives_fast.h"
|
||||
#include "doc/rgbmap.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
#endif
|
||||
|
20
src/doc/image_ref.h
Normal file
20
src/doc/image_ref.h
Normal file
@ -0,0 +1,20 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2014 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef DOC_IMAGE_REF_H_INCLUDED
|
||||
#define DOC_IMAGE_REF_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/shared_ptr.h"
|
||||
#include "doc/image.h"
|
||||
|
||||
namespace doc {
|
||||
|
||||
typedef SharedPtr<Image> ImageRef;
|
||||
|
||||
} // namespace doc
|
||||
|
||||
#endif
|
@ -14,7 +14,6 @@
|
||||
#include "doc/layer.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
namespace doc {
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
@ -118,12 +117,6 @@ void LayerImage::destroyAllCels()
|
||||
|
||||
for (; it != end; ++it) {
|
||||
Cel* cel = *it;
|
||||
Image* image = cel->image();
|
||||
|
||||
ASSERT(image != NULL);
|
||||
|
||||
sprite()->stock()->removeImage(image);
|
||||
delete image;
|
||||
delete cel;
|
||||
}
|
||||
m_cels.clear();
|
||||
@ -181,13 +174,15 @@ void LayerImage::addCel(Cel *cel)
|
||||
* It doesn't destroy the cel, you have to delete it after calling
|
||||
* this routine.
|
||||
*/
|
||||
void LayerImage::removeCel(Cel *cel)
|
||||
void LayerImage::removeCel(Cel* cel)
|
||||
{
|
||||
CelIterator it = std::find(m_cels.begin(), m_cels.end(), cel);
|
||||
|
||||
ASSERT(it != m_cels.end());
|
||||
|
||||
m_cels.erase(it);
|
||||
|
||||
cel->setParentLayer(NULL);
|
||||
}
|
||||
|
||||
void LayerImage::moveCel(Cel* cel, frame_t frame)
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/stock.h"
|
||||
#include "doc/subobjects_io.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
@ -27,7 +27,7 @@ using namespace base::serialization::little_endian;
|
||||
|
||||
// Serialized Layer data:
|
||||
|
||||
void write_layer(std::ostream& os, LayerSubObjectsSerializer* subObjects, Layer* layer)
|
||||
void write_layer(std::ostream& os, SubObjectsIO* subObjects, Layer* layer)
|
||||
{
|
||||
std::string name = layer->name();
|
||||
|
||||
@ -50,11 +50,6 @@ void write_layer(std::ostream& os, LayerSubObjectsSerializer* subObjects, Layer*
|
||||
for (; it != end; ++it) {
|
||||
Cel* cel = *it;
|
||||
subObjects->write_cel(os, cel);
|
||||
|
||||
Image* image = cel->image();
|
||||
ASSERT(image != NULL);
|
||||
|
||||
subObjects->write_image(os, image);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -74,7 +69,7 @@ void write_layer(std::ostream& os, LayerSubObjectsSerializer* subObjects, Layer*
|
||||
}
|
||||
}
|
||||
|
||||
Layer* read_layer(std::istream& is, LayerSubObjectsSerializer* subObjects, Sprite* sprite)
|
||||
Layer* read_layer(std::istream& is, SubObjectsIO* subObjects, Sprite* sprite)
|
||||
{
|
||||
uint16_t name_length = read16(is); // Name length
|
||||
std::vector<char> name(name_length+1);
|
||||
@ -104,11 +99,6 @@ Layer* read_layer(std::istream& is, LayerSubObjectsSerializer* subObjects, Sprit
|
||||
|
||||
// Add the cel in the layer
|
||||
static_cast<LayerImage*>(layer.get())->addCel(cel);
|
||||
|
||||
// Read the cel's image
|
||||
Image* image = subObjects->read_image(is);
|
||||
|
||||
sprite->stock()->replaceImage(cel->imageIndex(), image);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ namespace doc {
|
||||
class Image;
|
||||
class Layer;
|
||||
class Sprite;
|
||||
class SubObjectsIO;
|
||||
|
||||
// Thrown when a invalid layer type is read from the istream.
|
||||
class InvalidLayerType : public base::Exception {
|
||||
@ -25,24 +26,8 @@ namespace doc {
|
||||
InvalidLayerType(const char* msg) throw() : base::Exception(msg) { }
|
||||
};
|
||||
|
||||
// Interface used to read sub-objects of a layer.
|
||||
class LayerSubObjectsSerializer {
|
||||
public:
|
||||
virtual ~LayerSubObjectsSerializer() { }
|
||||
|
||||
// How to write cels, images, and sub-layers
|
||||
virtual void write_cel(std::ostream& os, Cel* cel) = 0;
|
||||
virtual void write_image(std::ostream& os, Image* image) = 0;
|
||||
virtual void write_layer(std::ostream& os, Layer* layer) = 0;
|
||||
|
||||
// How to read cels, images, and sub-layers
|
||||
virtual Cel* read_cel(std::istream& is) = 0;
|
||||
virtual Image* read_image(std::istream& is) = 0;
|
||||
virtual Layer* read_layer(std::istream& is) = 0;
|
||||
};
|
||||
|
||||
void write_layer(std::ostream& os, LayerSubObjectsSerializer* subObjects, Layer* layer);
|
||||
Layer* read_layer(std::istream& is, LayerSubObjectsSerializer* subObjects, Sprite* sprite);
|
||||
void write_layer(std::ostream& os, SubObjectsIO* subObjects, Layer* layer);
|
||||
Layer* read_layer(std::istream& is, SubObjectsIO* subObjects, Sprite* sprite);
|
||||
|
||||
} // namespace doc
|
||||
|
||||
|
@ -20,7 +20,6 @@ namespace doc {
|
||||
Cel,
|
||||
LayerImage,
|
||||
LayerFolder,
|
||||
Stock,
|
||||
Sprite,
|
||||
Document,
|
||||
};
|
||||
|
@ -38,7 +38,6 @@ Sprite::Sprite(PixelFormat format, int width, int height, int ncolors)
|
||||
ASSERT(width > 0 && height > 0);
|
||||
|
||||
m_frlens.push_back(100); // First frame with 100 msecs of duration
|
||||
m_stock = new Stock(this, format);
|
||||
m_folder = new LayerFolder(this);
|
||||
|
||||
// Generate palette
|
||||
@ -77,10 +76,6 @@ Sprite::~Sprite()
|
||||
// Destroy layers
|
||||
delete m_folder;
|
||||
|
||||
// Destroy images' stock
|
||||
if (m_stock)
|
||||
delete m_stock;
|
||||
|
||||
// Destroy palettes
|
||||
{
|
||||
PalettesList::iterator end = m_palettes.end();
|
||||
@ -101,17 +96,8 @@ Sprite* Sprite::createBasicSprite(doc::PixelFormat format, int width, int height
|
||||
sprite->setTotalFrames(doc::frame_t(1));
|
||||
|
||||
// Create the main image.
|
||||
int indexInStock;
|
||||
{
|
||||
base::UniquePtr<doc::Image> image(doc::Image::create(format, width, height));
|
||||
|
||||
// Clear the image with mask color.
|
||||
doc::clear_image(image, 0);
|
||||
|
||||
// Add image in the sprite's stock.
|
||||
indexInStock = sprite->stock()->addImage(image);
|
||||
image.release(); // Release the image because it is in the sprite's stock.
|
||||
}
|
||||
doc::ImageRef image(doc::Image::create(format, width, height));
|
||||
doc::clear_image(image, 0);
|
||||
|
||||
// Create the first transparent layer.
|
||||
{
|
||||
@ -120,7 +106,7 @@ Sprite* Sprite::createBasicSprite(doc::PixelFormat format, int width, int height
|
||||
|
||||
// Create the cel.
|
||||
{
|
||||
base::UniquePtr<doc::Cel> cel(new doc::Cel(doc::frame_t(0), indexInStock));
|
||||
base::UniquePtr<doc::Cel> cel(new doc::Cel(doc::frame_t(0), image));
|
||||
cel->setPosition(0, 0);
|
||||
|
||||
// Add the cel in the layer.
|
||||
@ -177,22 +163,20 @@ void Sprite::setTransparentColor(color_t color)
|
||||
m_transparentColor = color;
|
||||
|
||||
// Change the mask color of all images.
|
||||
for (int i=0; i<m_stock->size(); i++) {
|
||||
Image* image = m_stock->getImage(i);
|
||||
if (image != NULL)
|
||||
image->setMaskColor(color);
|
||||
}
|
||||
std::vector<Image*> images;
|
||||
getImages(images);
|
||||
for (Image* image : images)
|
||||
image->setMaskColor(color);
|
||||
}
|
||||
|
||||
int Sprite::getMemSize() const
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
for (int i=0; i<m_stock->size(); i++) {
|
||||
Image* image = m_stock->getImage(i);
|
||||
if (image != NULL)
|
||||
size += image->getRowStrideSize() * image->height();
|
||||
}
|
||||
std::vector<Image*> images;
|
||||
getImages(images);
|
||||
for (Image* image : images)
|
||||
size += image->getRowStrideSize() * image->height();
|
||||
|
||||
return size;
|
||||
}
|
||||
@ -410,9 +394,25 @@ void Sprite::setDurationForAllFrames(int msecs)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Images
|
||||
|
||||
Stock* Sprite::stock() const
|
||||
ImageRef Sprite::getImage(ObjectId imageId)
|
||||
{
|
||||
return m_stock;
|
||||
CelList cels;
|
||||
getCels(cels);
|
||||
for (auto& cel : cels) {
|
||||
if (cel->image()->id() == imageId)
|
||||
return cel->imageRef();
|
||||
}
|
||||
return ImageRef(NULL);
|
||||
}
|
||||
|
||||
void Sprite::replaceImage(ObjectId curImageId, const ImageRef& newImage)
|
||||
{
|
||||
CelList cels;
|
||||
getCels(cels);
|
||||
for (auto& cel : cels) {
|
||||
if (cel->image()->id() == curImageId)
|
||||
cel->setImage(newImage);
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite::getCels(CelList& cels) const
|
||||
@ -420,17 +420,15 @@ void Sprite::getCels(CelList& cels) const
|
||||
folder()->getCels(cels);
|
||||
}
|
||||
|
||||
size_t Sprite::getImageRefs(int imageIndex) const
|
||||
// TODO replace it with a images iterator
|
||||
void Sprite::getImages(std::vector<Image*>& images) const
|
||||
{
|
||||
CelList cels;
|
||||
getCels(cels);
|
||||
getCels(cels); // TODO create a cel iterator
|
||||
|
||||
size_t refs = 0;
|
||||
for (CelList::iterator it=cels.begin(), end=cels.end(); it != end; ++it)
|
||||
if ((*it)->imageIndex() == imageIndex)
|
||||
++refs;
|
||||
|
||||
return refs;
|
||||
for (const auto& cel : cels)
|
||||
if (!cel->link())
|
||||
images.push_back(cel->image());
|
||||
}
|
||||
|
||||
void Sprite::remapImages(frame_t frameFrom, frame_t frameTo, const std::vector<uint8_t>& mapping)
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "doc/cel_list.h"
|
||||
#include "doc/color.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/layer_index.h"
|
||||
#include "doc/object.h"
|
||||
#include "doc/pixel_format.h"
|
||||
@ -31,7 +32,6 @@ namespace doc {
|
||||
class Path;
|
||||
class RgbMap;
|
||||
class Sprite;
|
||||
class Stock;
|
||||
|
||||
typedef std::vector<Palette*> PalettesList;
|
||||
|
||||
@ -116,26 +116,20 @@ namespace doc {
|
||||
////////////////////////////////////////
|
||||
// Images
|
||||
|
||||
Stock* stock() const;
|
||||
|
||||
ImageRef getImage(ObjectId imageId);
|
||||
void replaceImage(ObjectId curImageId, const ImageRef& newImage);
|
||||
void getCels(CelList& cels) const;
|
||||
|
||||
// Returns the how many cels are referencing the given imageIndex.
|
||||
size_t getImageRefs(int imageIndex) const;
|
||||
|
||||
void getImages(std::vector<Image*>& images) const;
|
||||
void remapImages(frame_t frameFrom, frame_t frameTo, const std::vector<uint8_t>& mapping);
|
||||
|
||||
void pickCels(int x, int y, frame_t frame, int opacityThreshold, CelList& cels) const;
|
||||
|
||||
private:
|
||||
Sprite* m_self; // pointer to the Sprite
|
||||
PixelFormat m_format; // pixel format
|
||||
int m_width; // image width (in pixels)
|
||||
int m_height; // image height (in pixels)
|
||||
frame_t m_frames; // how many frames has this sprite
|
||||
std::vector<int> m_frlens; // duration per frame
|
||||
PalettesList m_palettes; // list of palettes
|
||||
Stock* m_stock; // stock to get images
|
||||
LayerFolder* m_folder; // main folder of layers
|
||||
|
||||
// Current rgb map
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/stock.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -1,91 +0,0 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2014 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "doc/stock.h"
|
||||
|
||||
#include "doc/image.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace doc {
|
||||
|
||||
Stock::Stock(Sprite* sprite, PixelFormat format)
|
||||
: Object(ObjectType::Stock)
|
||||
, m_format(format)
|
||||
, m_sprite(sprite)
|
||||
{
|
||||
// Image with index=0 is always NULL.
|
||||
m_image.push_back(NULL);
|
||||
}
|
||||
|
||||
Stock::~Stock()
|
||||
{
|
||||
for (int i=0; i<size(); ++i) {
|
||||
if (getImage(i))
|
||||
delete getImage(i);
|
||||
}
|
||||
}
|
||||
|
||||
Sprite* Stock::sprite() const
|
||||
{
|
||||
return m_sprite;
|
||||
}
|
||||
|
||||
Image* Stock::getImage(int index) const
|
||||
{
|
||||
ASSERT((index >= 0) && (index < size()));
|
||||
|
||||
return m_image[index];
|
||||
}
|
||||
|
||||
int Stock::addImage(Image* image)
|
||||
{
|
||||
int i = m_image.size();
|
||||
try {
|
||||
m_image.resize(m_image.size()+1);
|
||||
}
|
||||
catch (...) {
|
||||
delete image;
|
||||
throw;
|
||||
}
|
||||
m_image[i] = image;
|
||||
|
||||
fixupImage(image);
|
||||
return i;
|
||||
}
|
||||
|
||||
void Stock::removeImage(Image* image)
|
||||
{
|
||||
for (int i=0; i<size(); i++)
|
||||
if (m_image[i] == image) {
|
||||
m_image[i] = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(false && "The specified image was not found");
|
||||
}
|
||||
|
||||
void Stock::replaceImage(int index, Image* image)
|
||||
{
|
||||
ASSERT((index > 0) && (index < size()));
|
||||
m_image[index] = image;
|
||||
|
||||
fixupImage(image);
|
||||
}
|
||||
|
||||
void Stock::fixupImage(Image* image)
|
||||
{
|
||||
// Change the mask color of the added image to the sprite mask color.
|
||||
if (image)
|
||||
image->setMaskColor(m_sprite->transparentColor());
|
||||
}
|
||||
|
||||
} // namespace doc
|
@ -1,70 +0,0 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2014 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef DOC_STOCK_H_INCLUDED
|
||||
#define DOC_STOCK_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/disable_copying.h"
|
||||
#include "doc/object.h"
|
||||
#include "doc/pixel_format.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace doc {
|
||||
|
||||
class Image;
|
||||
class Sprite;
|
||||
|
||||
typedef std::vector<Image*> ImagesList;
|
||||
|
||||
class Stock : public Object {
|
||||
public:
|
||||
Stock(Sprite* sprite, PixelFormat format);
|
||||
virtual ~Stock();
|
||||
|
||||
Sprite* sprite() const;
|
||||
|
||||
// Returns the number of image in the stock.
|
||||
int size() const {
|
||||
return m_image.size();
|
||||
}
|
||||
|
||||
// Returns the image in the "index" position
|
||||
Image* getImage(int index) const;
|
||||
|
||||
// Adds a new image in the stock resizing the images-array. Returns
|
||||
// the index/position in the stock (this index can be used with the
|
||||
// Stock::getImage() function).
|
||||
int addImage(Image* image);
|
||||
|
||||
// Removes a image from the stock, it doesn't resize the stock.
|
||||
void removeImage(Image* image);
|
||||
|
||||
// Replaces the image in the stock in the "index" position with the
|
||||
// new "image"; you must delete the old image before, e.g:
|
||||
//
|
||||
// Image* old_image = stock->getImage(index);
|
||||
// if (old_image)
|
||||
// delete old_image;
|
||||
// stock->replaceImage(index, new_image);
|
||||
//
|
||||
void replaceImage(int index, Image* image);
|
||||
|
||||
private:
|
||||
void fixupImage(Image* image);
|
||||
|
||||
PixelFormat m_format; // Type of images (all images in the stock must be of this type).
|
||||
ImagesList m_image; // The images-array where the images are.
|
||||
Sprite* m_sprite;
|
||||
|
||||
Stock();
|
||||
DISABLE_COPYING(Stock);
|
||||
};
|
||||
|
||||
} // namespace doc
|
||||
|
||||
#endif
|
37
src/doc/subobjects_io.h
Normal file
37
src/doc/subobjects_io.h
Normal file
@ -0,0 +1,37 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2014 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef DOC_SUBOBJECTS_IO_H_INCLUDED
|
||||
#define DOC_SUBOBJECTS_IO_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace doc {
|
||||
|
||||
class Cel;
|
||||
class Image;
|
||||
class Layer;
|
||||
|
||||
// Interface used to read sub-objects of a layer or cel.
|
||||
class SubObjectsIO {
|
||||
public:
|
||||
virtual ~SubObjectsIO() { }
|
||||
|
||||
// How to write cels, images, and sub-layers
|
||||
virtual void write_cel(std::ostream& os, Cel* cel) = 0;
|
||||
virtual void write_image(std::ostream& os, Image* image) = 0;
|
||||
virtual void write_layer(std::ostream& os, Layer* layer) = 0;
|
||||
|
||||
// How to read cels, images, and sub-layers
|
||||
virtual Cel* read_cel(std::istream& is) = 0;
|
||||
virtual Image* read_image(std::istream& is) = 0;
|
||||
virtual Layer* read_layer(std::istream& is) = 0;
|
||||
};
|
||||
|
||||
} // namespace doc
|
||||
|
||||
#endif
|
@ -21,7 +21,6 @@ namespace doc {
|
||||
class Palette;
|
||||
class RgbMap;
|
||||
class Sprite;
|
||||
class Stock;
|
||||
}
|
||||
|
||||
namespace render {
|
||||
|
Loading…
x
Reference in New Issue
Block a user