Separate extra cel concept from app::Document into app::ExtraCel class

This commit is contained in:
David Capello 2015-08-19 10:03:29 -03:00
parent b2049f7ce4
commit a39e3710ce
13 changed files with 167 additions and 114 deletions

View File

@ -258,6 +258,7 @@ add_library(app-lib
document_range.cpp
document_range_ops.cpp
document_undo.cpp
extra_cel.cpp
file/ase_format.cpp
file/bmp_format.cpp
file/file.cpp

View File

@ -105,7 +105,7 @@ void SetPixelFormat::setFormat(PixelFormat format)
// Regenerate extras
static_cast<app::Document*>(sprite->document())
->destroyExtraCel();
->setExtraCel(ExtraCelRef(nullptr));
// Generate notification
DocumentEvent ev(sprite->document());

View File

@ -66,7 +66,7 @@ public:
editor->getManager()->freeMouse();
// Clear extras (e.g. pen preview)
m_doc->destroyExtraCel();
m_doc->setExtraCel(ExtraCelRef(nullptr));
gfx::Rect vp = view->getViewportBounds();
gfx::Point scroll = view->getViewScroll();

View File

@ -122,7 +122,7 @@ void UndoCommand::onExecute(Context* context)
}
document->generateMaskBoundaries();
document->destroyExtraCel(); // Regenerate extras
document->setExtraCel(ExtraCelRef(nullptr));
update_screen_for_document(document);
set_current_palette(writer.palette(), false);

View File

@ -51,12 +51,6 @@ Document::Document(Sprite* sprite)
, m_read_locks(0)
// Information about the file format used to load/save this document
, m_format_options(NULL)
// Extra cel
, m_extraCel(nullptr)
, m_extraImage(nullptr)
, m_extraImageBuffer(nullptr)
, m_extraCelBlendMode(BlendMode::NORMAL)
, m_extraCelType(render::ExtraType::NONE)
// Mask
, m_mask(new Mask())
, m_maskVisible(true)
@ -75,8 +69,6 @@ Document::~Document()
// which could result in serious problems for observers expecting a
// fully created app::Document.
ASSERT(context() == NULL);
destroyExtraCel();
}
DocumentApi Document::getApi(Transaction& transaction)
@ -232,55 +224,6 @@ void Document::generateMaskBoundaries(const Mask* mask)
notifySelectionChanged();
}
//////////////////////////////////////////////////////////////////////
// Extra Cel (it is used to draw pen preview, pixels in movement, etc.)
void Document::destroyExtraCel()
{
delete m_extraCel;
m_extraCel = nullptr;
m_extraImage.reset(nullptr);
m_extraCelType = render::ExtraType::NONE;
}
void Document::prepareExtraCel(const gfx::Rect& bounds, frame_t frame, int opacity)
{
ASSERT(sprite() != NULL);
if (!m_extraImage ||
m_extraImage->pixelFormat() != sprite()->pixelFormat() ||
m_extraImage->width() != bounds.w ||
m_extraImage->height() != bounds.h) {
if (!m_extraImageBuffer)
m_extraImageBuffer.reset(new ImageBuffer(1));
Image* newImage = Image::create(sprite()->pixelFormat(), bounds.w, bounds.h, m_extraImageBuffer);
m_extraImage.reset(newImage);
}
if (!m_extraCel)
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);
m_extraCel->setFrame(frame);
}
void Document::setExtraCelType(render::ExtraType type)
{
m_extraCelType = type;
}
Cel* Document::getExtraCel() const
{
return m_extraCel;
}
Image* Document::getExtraCelImage() const
{
return m_extraImage.get();
}
//////////////////////////////////////////////////////////////////////
// Mask

View File

@ -9,6 +9,7 @@
#define APP_DOCUMENT_H_INCLUDED
#pragma once
#include "app/extra_cel.h"
#include "app/file/format_options.h"
#include "base/disable_copying.h"
#include "base/mutex.h"
@ -19,12 +20,9 @@
#include "doc/color.h"
#include "doc/document.h"
#include "doc/frame.h"
#include "doc/image_ref.h"
#include "doc/image_buffer.h"
#include "doc/pixel_format.h"
#include "gfx/rect.h"
#include "gfx/transformation.h"
#include "render/extra_type.h"
#include <string>
@ -123,14 +121,8 @@ namespace app {
//////////////////////////////////////////////////////////////////////
// Extra Cel (it is used to draw pen preview, pixels in movement, etc.)
void prepareExtraCel(const gfx::Rect& bounds, frame_t frame, int opacity);
void setExtraCelType(render::ExtraType type);
void destroyExtraCel();
Cel* getExtraCel() const;
Image* getExtraCelImage() const;
render::ExtraType getExtraCelType() const { return m_extraCelType; }
BlendMode getExtraCelBlendMode() const { return m_extraCelBlendMode; }
void setExtraCelBlendMode(BlendMode mode) { m_extraCelBlendMode = mode; }
ExtraCelRef extraCel() const { return m_extraCel; }
void setExtraCel(const ExtraCelRef& extraCel) { m_extraCel = extraCel; }
//////////////////////////////////////////////////////////////////////
// Mask
@ -210,13 +202,7 @@ namespace app {
base::SharedPtr<FormatOptions> m_format_options;
// Extra cel used to draw extra stuff (e.g. editor's pen preview, pixels in movement, etc.)
Cel* m_extraCel;
// Image of the extra cel.
ImageRef m_extraImage;
ImageBufferPtr m_extraImageBuffer;
BlendMode m_extraCelBlendMode;
render::ExtraType m_extraCelType;
ExtraCelRef m_extraCel;
// Current mask.
base::UniquePtr<Mask> m_mask;

53
src/app/extra_cel.cpp Normal file
View File

@ -0,0 +1,53 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/extra_cel.h"
#include "doc/sprite.h"
namespace app {
ExtraCel::ExtraCel()
: m_type(render::ExtraType::NONE)
, m_blendMode(doc::BlendMode::NORMAL)
{
}
void ExtraCel::create(doc::Sprite* sprite,
const gfx::Rect& bounds,
doc::frame_t frame,
int opacity)
{
ASSERT(sprite);
if (!m_image ||
m_image->pixelFormat() != sprite->pixelFormat() ||
m_image->width() != bounds.w ||
m_image->height() != bounds.h) {
if (!m_imageBuffer)
m_imageBuffer.reset(new doc::ImageBuffer(1));
doc::Image* newImage = doc::Image::create(sprite->pixelFormat(),
bounds.w, bounds.h,
m_imageBuffer);
m_image.reset(newImage);
}
if (!m_cel) {
// Ignored fields for this cel (frame, and image index)
m_cel.reset(new doc::Cel(doc::frame_t(0), doc::ImageRef(nullptr)));
}
m_cel->setPosition(bounds.getOrigin());
m_cel->setOpacity(opacity);
m_cel->setFrame(frame);
}
} // namespace app

58
src/app/extra_cel.h Normal file
View File

@ -0,0 +1,58 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_EXTRA_CEL_H_INCLUDED
#define APP_EXTRA_CEL_H_INCLUDED
#pragma once
#include "base/disable_copying.h"
#include "base/unique_ptr.h"
#include "doc/blend_mode.h"
#include "doc/cel.h"
#include "doc/frame.h"
#include "doc/image_buffer.h"
#include "doc/image_ref.h"
#include "gfx/rect.h"
#include "render/extra_type.h"
namespace doc {
class Sprite;
}
namespace app {
class ExtraCel {
public:
ExtraCel();
void create(doc::Sprite* sprite, const gfx::Rect& bounds, doc::frame_t frame, int opacity);
void destroy();
render::ExtraType type() const { return m_type; }
void setType(render::ExtraType type) { m_type = type; }
doc::Cel* cel() const { return m_cel.get(); }
doc::Image* image() const { return m_image.get(); }
doc::BlendMode blendMode() const { return m_blendMode; }
void setBlendMode(doc::BlendMode mode) { m_blendMode = mode; }
private:
render::ExtraType m_type;
base::UniquePtr<doc::Cel> m_cel;
doc::ImageRef m_image;
doc::ImageBufferPtr m_imageBuffer;
doc::BlendMode m_blendMode;
DISABLE_COPYING(ExtraCel);
};
typedef base::SharedPtr<ExtraCel> ExtraCelRef;
} // namespace app
#endif

View File

@ -155,13 +155,17 @@ void BrushPreview::show(const gfx::Point& screenPos)
if (cel) opacity = MUL_UN8(opacity, cel->opacity(), t);
if (layer) opacity = MUL_UN8(opacity, static_cast<LayerImage*>(layer)->opacity(), t);
document->prepareExtraCel(brushBounds, site.frame(), opacity);
document->setExtraCelType(render::ExtraType::NONE);
document->setExtraCelBlendMode(
if (!m_extraCel)
m_extraCel.reset(new ExtraCel);
m_extraCel->create(document->sprite(), brushBounds, site.frame(), opacity);
m_extraCel->setType(render::ExtraType::NONE);
m_extraCel->setBlendMode(
(layer ? static_cast<LayerImage*>(layer)->blendMode():
BlendMode::NORMAL));
Image* extraImage = document->getExtraCelImage();
document->setExtraCel(m_extraCel);
Image* extraImage = m_extraCel->image();
extraImage->setMaskColor(mask_index);
clear_image(extraImage,
(extraImage->pixelFormat() == IMAGE_INDEXED ? mask_index: 0));
@ -173,7 +177,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
BlendMode::SRC);
// This extra cel is a patch for the current layer/frame
document->setExtraCelType(render::ExtraType::PATCH);
m_extraCel->setType(render::ExtraType::PATCH);
}
tools::ToolLoop* loop = create_tool_loop_preview(
@ -247,7 +251,7 @@ void BrushPreview::hide()
// Clean pixel/brush preview
if (m_withRealPreview) {
document->destroyExtraCel();
document->setExtraCel(ExtraCelRef(nullptr));
document->notifySpritePixelsModified(
sprite, gfx::Region(m_lastBounds), m_lastFrame);

View File

@ -9,6 +9,7 @@
#define APP_UI_EDITOR_BRUSH_PREVIEW_H_INCLUDED
#pragma once
#include "app/extra_cel.h"
#include "base/shared_ptr.h"
#include "doc/color.h"
#include "doc/frame.h"
@ -106,6 +107,8 @@ namespace app {
// brush preview in the exact same place.
gfx::Rect m_lastBounds;
doc::frame_t m_lastFrame;
ExtraCelRef m_extraCel;
};
class HideBrushPreview {

View File

@ -479,14 +479,13 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
}
}
if (m_document->getExtraCelType() != render::ExtraType::NONE) {
ASSERT(m_document->getExtraCel());
ExtraCelRef extraCel = m_document->extraCel();
if (extraCel && extraCel->type() != render::ExtraType::NONE) {
m_renderEngine.setExtraImage(
m_document->getExtraCelType(),
m_document->getExtraCel(),
m_document->getExtraCelImage(),
m_document->getExtraCelBlendMode(),
extraCel->type(),
extraCel->cel(),
extraCel->image(),
extraCel->blendMode(),
m_layer, m_frame);
}
@ -794,22 +793,24 @@ void Editor::flashCurrentLayer()
if (src_image) {
m_renderEngine.removePreviewImage();
m_document->prepareExtraCel(m_sprite->bounds(), m_frame, 255);
m_document->setExtraCelType(render::ExtraType::COMPOSITE);
Image* flash_image = m_document->getExtraCelImage();
ExtraCelRef extraCel(new ExtraCel);
extraCel->create(m_sprite, m_sprite->bounds(), m_frame, 255);
extraCel->setType(render::ExtraType::COMPOSITE);
extraCel->setBlendMode(BlendMode::NEG_BW);
Image* flash_image = extraCel->image();
clear_image(flash_image, flash_image->maskColor());
copy_image(flash_image, src_image, x, y);
m_document->setExtraCelBlendMode(BlendMode::NEG_BW);
drawSpriteClipped(gfx::Region(
gfx::Rect(0, 0, m_sprite->width(), m_sprite->height())));
{
ExtraCelRef oldExtraCel = m_document->extraCel();
m_document->setExtraCel(extraCel);
drawSpriteClipped(gfx::Region(
gfx::Rect(0, 0, m_sprite->width(), m_sprite->height())));
getManager()->flipDisplay();
m_document->setExtraCel(oldExtraCel);
}
getManager()->flipDisplay();
m_document->setExtraCelBlendMode(BlendMode::NORMAL);
m_document->destroyExtraCel();
invalidate();
}
}

View File

@ -89,7 +89,7 @@ PixelsMovement::PixelsMovement(
// The extra cel must be null, because if it's not null, it means
// that someone else is using it (e.g. the editor brush preview),
// and its owner could destroy our new "extra cel".
ASSERT(!m_document->getExtraCel());
ASSERT(!m_document->extraCel());
redrawExtraImage();
redrawCurrentMask();
@ -491,8 +491,8 @@ void PixelsMovement::getDraggedImageCopy(base::UniquePtr<Image>& outputImage,
void PixelsMovement::stampImage()
{
const Cel* cel = m_document->getExtraCel();
const Image* image = m_document->getExtraCelImage();
const Cel* cel = m_extraCel->cel();
const Image* image = m_extraCel->image();
ASSERT(cel && image);
@ -583,7 +583,7 @@ void PixelsMovement::dropImage()
// Destroy the extra cel (this cel will be used by the drawing
// cursor surely).
ContextWriter writer(m_reader, 1000);
m_document->destroyExtraCel();
m_document->setExtraCel(ExtraCelRef(nullptr));
}
void PixelsMovement::discardImage(bool commit)
@ -599,7 +599,7 @@ void PixelsMovement::discardImage(bool commit)
// Destroy the extra cel and regenerate the mask boundaries (we've
// just deselect the mask).
ContextWriter writer(m_reader, 1000);
m_document->destroyExtraCel();
m_document->setExtraCel(ExtraCelRef(nullptr));
m_document->generateMaskBoundaries();
}
@ -610,8 +610,8 @@ bool PixelsMovement::isDragging() const
gfx::Rect PixelsMovement::getImageBounds()
{
const Cel* cel = m_document->getExtraCel();
const Image* image = m_document->getExtraCelImage();
const Cel* cel = m_extraCel->cel();
const Image* image = m_extraCel->image();
ASSERT(cel != NULL);
ASSERT(image != NULL);
@ -641,14 +641,16 @@ void PixelsMovement::redrawExtraImage()
if (cel) opacity = MUL_UN8(opacity, cel->opacity(), t);
gfx::Rect bounds = m_currentData.transformedBounds();
m_document->prepareExtraCel(bounds, m_site.frame(), opacity);
m_document->setExtraCelType(render::ExtraType::PATCH);
m_document->setExtraCelBlendMode(
static_cast<LayerImage*>(m_layer)->blendMode());
m_extraCel.reset(new ExtraCel);
m_extraCel->create(m_document->sprite(), bounds, m_site.frame(), opacity);
m_extraCel->setType(render::ExtraType::PATCH);
m_extraCel->setBlendMode(static_cast<LayerImage*>(m_layer)->blendMode());
m_document->setExtraCel(m_extraCel);
// Draw the transformed pixels in the extra-cel which is the chunk
// of pixels that the user is moving.
drawImage(m_document->getExtraCelImage(), bounds.getOrigin(), true);
drawImage(m_extraCel->image(), bounds.getOrigin(), true);
}
void PixelsMovement::redrawCurrentMask()

View File

@ -10,6 +10,7 @@
#pragma once
#include "app/context_access.h"
#include "app/extra_cel.h"
#include "app/transaction.h"
#include "app/ui/editor/handle_type.h"
#include "base/connection.h"
@ -125,6 +126,7 @@ namespace app {
ScopedConnection m_pivotVisConn;
ScopedConnection m_pivotPosConn;
ScopedConnection m_rotAlgoConn;
ExtraCelRef m_extraCel;
};
inline PixelsMovement::MoveModifier& operator|=(PixelsMovement::MoveModifier& a,