mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-01 01:20:25 +00:00
Timeline: add support to move/copy ranges (multiple cels/frames/layers)
- Merge Timeline::STATE_MOVING_LAYER/CEL/FRAME to STATE_MOVING_RANGE. - Remove celmove.h/cpp and move_cel/copy_cel functions. Now they are in the Timeline as dropRange/Cels/Frames/Layers member functions. - Add DocumentApi::copyFrame/moveCel/copyCel member functions. - Add timeline_drop_layer_deco and timeline_drop_frame_deco skin parts. - Move code from DuplicateLayerCommand::onExecute() to new member function DocumentApi::duplicateLayer(). - Fix a bug changing Cel's frame number: we weren't updating the Cel position properly inside the LayerImage::m_cels collection. Now we use LayerImage::moveCel() to change the Cel frame number. - Other fixes to DocumentApi: Change bgcolor from int to color_t.
This commit is contained in:
parent
cb2c094212
commit
942dba36fd
Binary file not shown.
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@ -310,6 +310,8 @@
|
||||
<part id="timeline_padding_tr" x="288" y="12" w1="1" w2="10" w3="1" h1="1" h2="10" h3="1" />
|
||||
<part id="timeline_padding_bl" x="276" y="24" w1="1" w2="10" w3="1" h1="1" h2="10" h3="1" />
|
||||
<part id="timeline_padding_br" x="288" y="24" w1="1" w2="10" w3="1" h1="1" h2="10" h3="1" />
|
||||
<part id="timeline_drop_layer_deco" x="252" y="127" w1="3" w2="1" w3="3" h1="2" h2="1" h3="2" />
|
||||
<part id="timeline_drop_frame_deco" x="252" y="120" w1="2" w2="1" w3="2" h1="3" h2="1" h3="3" />
|
||||
</parts>
|
||||
|
||||
<stylesheet>
|
||||
@ -502,6 +504,16 @@
|
||||
<background part="colorbar_border_fg" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_drop_layer_deco -->
|
||||
<style id="timeline_drop_layer_deco">
|
||||
<background part="timeline_drop_layer_deco" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_drop_frame_deco -->
|
||||
<style id="timeline_drop_frame_deco">
|
||||
<background part="timeline_drop_frame_deco" />
|
||||
</style>
|
||||
|
||||
</stylesheet>
|
||||
|
||||
</skin>
|
||||
|
@ -227,7 +227,6 @@ add_library(app-lib
|
||||
undoers/set_total_frames.cpp
|
||||
util/autocrop.cpp
|
||||
util/boundary.cpp
|
||||
util/celmove.cpp
|
||||
util/clipboard.cpp
|
||||
util/expand_cel_canvas.cpp
|
||||
util/filetoks.cpp
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "app/context_access.h"
|
||||
#include "app/ui/timeline.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/util/celmove.h"
|
||||
#include "ui/base.h"
|
||||
|
||||
namespace app {
|
||||
@ -54,8 +53,7 @@ bool CopyCelCommand::onEnabled(Context* context)
|
||||
|
||||
void CopyCelCommand::onExecute(Context* context)
|
||||
{
|
||||
ContextWriter writer(context);
|
||||
copy_cel(writer);
|
||||
App::instance()->getMainWindow()->getTimeline()->dropRange(Timeline::kCopy);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createCopyCelCommand()
|
||||
|
@ -66,33 +66,14 @@ void DuplicateLayerCommand::onExecute(Context* context)
|
||||
{
|
||||
ContextWriter writer(context);
|
||||
Document* document = writer.document();
|
||||
Sprite* sprite = writer.sprite();
|
||||
UndoTransaction undo(writer.context(), "Layer Duplication");
|
||||
LayerImage* sourceLayer = static_cast<LayerImage*>(writer.layer());
|
||||
DocumentApi api = document->getApi();
|
||||
|
||||
// Create a new layer
|
||||
base::UniquePtr<LayerImage> newLayerPtr(new LayerImage(sprite));
|
||||
|
||||
// Disable undo because the layer content is added as a whole with
|
||||
// AddLayer() undoer.
|
||||
document->getUndo()->setEnabled(false);
|
||||
|
||||
// Copy the layer content (cels + images)
|
||||
document->copyLayerContent(sourceLayer, document, newLayerPtr);
|
||||
|
||||
// Restore enabled status.
|
||||
document->getUndo()->setEnabled(undo.isEnabled());
|
||||
|
||||
// Copy the layer name
|
||||
newLayerPtr->setName(newLayerPtr->getName() + " Copy");
|
||||
|
||||
// Add the new layer in the sprite.
|
||||
document->getApi().addLayer(sourceLayer->getParent(), newLayerPtr, sourceLayer);
|
||||
|
||||
// Release the pointer as it is owned by the sprite now
|
||||
Layer* newLayer = newLayerPtr.release();
|
||||
|
||||
undo.commit();
|
||||
{
|
||||
UndoTransaction undo(writer.context(), "Layer Duplication");
|
||||
LayerImage* sourceLayer = static_cast<LayerImage*>(writer.layer());
|
||||
api.duplicateLayer(sourceLayer, sourceLayer);
|
||||
undo.commit();
|
||||
}
|
||||
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "app/context_access.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/timeline.h"
|
||||
#include "app/util/celmove.h"
|
||||
#include "ui/base.h"
|
||||
|
||||
namespace app {
|
||||
@ -54,8 +53,7 @@ bool MoveCelCommand::onEnabled(Context* context)
|
||||
|
||||
void MoveCelCommand::onExecute(Context* context)
|
||||
{
|
||||
ContextWriter writer(context);
|
||||
move_cel(writer);
|
||||
App::instance()->getMainWindow()->getTimeline()->dropRange(Timeline::kMove);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createMoveCelCommand()
|
||||
|
@ -360,8 +360,6 @@ void Document::resetTransformation()
|
||||
|
||||
void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, Layer* destLayer0) const
|
||||
{
|
||||
DocumentUndo* undo = destDoc->getUndo();
|
||||
|
||||
// Copy the layer name
|
||||
destLayer0->setName(sourceLayer0->getName());
|
||||
|
||||
@ -386,12 +384,6 @@ void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, La
|
||||
Image* newImage = Image::createCopy(sourceImage);
|
||||
newCel->setImage(destLayer->getSprite()->getStock()->addImage(newImage));
|
||||
|
||||
if (undo->isEnabled()) {
|
||||
undo->pushUndoer(new undoers::AddImage(undo->getObjects(),
|
||||
destLayer->getSprite()->getStock(),
|
||||
newCel->getImage()));
|
||||
}
|
||||
|
||||
destLayer->addCel(newCel);
|
||||
newCel.release();
|
||||
}
|
||||
@ -422,9 +414,14 @@ void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, La
|
||||
ASSERT(destChild != NULL);
|
||||
|
||||
// Add the new layer in the sprite.
|
||||
destDoc->getApi().addLayer(destLayer,
|
||||
destChild.release(),
|
||||
destLayer->getLastLayer());
|
||||
|
||||
Layer* newLayer = destChild.release();
|
||||
Layer* afterThis = destLayer->getLastLayer();
|
||||
|
||||
destLayer->addLayer(newLayer);
|
||||
destChild.release();
|
||||
|
||||
destLayer->stackLayer(newLayer, afterThis);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -461,14 +458,8 @@ Document* Document::duplicate(DuplicateType type) const
|
||||
switch (type) {
|
||||
|
||||
case DuplicateExactCopy:
|
||||
// Disable the undo
|
||||
documentCopy->getUndo()->setEnabled(false);
|
||||
|
||||
// Copy the layer folder
|
||||
copyLayerContent(getSprite()->getFolder(), documentCopy, spriteCopy->getFolder());
|
||||
|
||||
// Re-enable the undo
|
||||
documentCopy->getUndo()->setEnabled(true);
|
||||
break;
|
||||
|
||||
case DuplicateWithFlattenLayers:
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "app/undoers/remove_palette.h"
|
||||
#include "app/undoers/replace_image.h"
|
||||
#include "app/undoers/set_cel_frame.h"
|
||||
#include "app/undoers/set_cel_opacity.h"
|
||||
#include "app/undoers/set_cel_position.h"
|
||||
#include "app/undoers/set_frame_duration.h"
|
||||
#include "app/undoers/set_layer_flags.h"
|
||||
@ -71,8 +72,6 @@
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
|
||||
|
||||
|
||||
namespace app {
|
||||
|
||||
DocumentApi::DocumentApi(Document* document, undo::UndoersCollector* undoers)
|
||||
@ -101,7 +100,7 @@ void DocumentApi::setSpriteSize(Sprite* sprite, int w, int h)
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onSpriteSizeChanged, ev);
|
||||
}
|
||||
|
||||
void DocumentApi::cropSprite(Sprite* sprite, const gfx::Rect& bounds, int bgcolor)
|
||||
void DocumentApi::cropSprite(Sprite* sprite, const gfx::Rect& bounds, color_t bgcolor)
|
||||
{
|
||||
setSpriteSize(sprite, bounds.w, bounds.h);
|
||||
displaceLayers(sprite->getFolder(), -bounds.x, -bounds.y);
|
||||
@ -115,7 +114,7 @@ void DocumentApi::cropSprite(Sprite* sprite, const gfx::Rect& bounds, int bgcolo
|
||||
m_document->getMask()->getBounds().y-bounds.y);
|
||||
}
|
||||
|
||||
void DocumentApi::trimSprite(Sprite* sprite, int bgcolor)
|
||||
void DocumentApi::trimSprite(Sprite* sprite, color_t bgcolor)
|
||||
{
|
||||
gfx::Rect bounds;
|
||||
|
||||
@ -210,9 +209,11 @@ void DocumentApi::setPixelFormat(Sprite* sprite, PixelFormat newFormat, Ditherin
|
||||
|
||||
void DocumentApi::addFrame(Sprite* sprite, FrameNumber newFrame)
|
||||
{
|
||||
// Move cels, and create copies of the cels in the given "newFrame".
|
||||
addFrameForLayer(sprite->getFolder(), newFrame);
|
||||
copyFrame(sprite, newFrame.previous(), newFrame);
|
||||
}
|
||||
|
||||
void DocumentApi::copyFrame(Sprite* sprite, FrameNumber fromFrame, FrameNumber newFrame)
|
||||
{
|
||||
// Add the frame in the sprite structure, it adjusts the total
|
||||
// number of frames in the sprite.
|
||||
if (undoEnabled())
|
||||
@ -220,6 +221,9 @@ void DocumentApi::addFrame(Sprite* sprite, FrameNumber newFrame)
|
||||
|
||||
sprite->addFrame(newFrame);
|
||||
|
||||
// Move cels, and create copies of the cels in the given "newFrame".
|
||||
copyFrameForLayer(sprite->getFolder(), fromFrame, newFrame);
|
||||
|
||||
// Notify observers about the new frame.
|
||||
DocumentEvent ev(m_document);
|
||||
ev.sprite(sprite);
|
||||
@ -227,7 +231,7 @@ void DocumentApi::addFrame(Sprite* sprite, FrameNumber newFrame)
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onAddFrame, ev);
|
||||
}
|
||||
|
||||
void DocumentApi::addFrameForLayer(Layer* layer, FrameNumber frame)
|
||||
void DocumentApi::copyFrameForLayer(Layer* layer, FrameNumber fromFrame, FrameNumber frame)
|
||||
{
|
||||
ASSERT(layer);
|
||||
ASSERT(frame >= 0);
|
||||
@ -236,60 +240,35 @@ void DocumentApi::addFrameForLayer(Layer* layer, FrameNumber frame)
|
||||
|
||||
switch (layer->type()) {
|
||||
|
||||
case OBJECT_LAYER_IMAGE:
|
||||
case OBJECT_LAYER_IMAGE: {
|
||||
LayerImage* imglayer = static_cast<LayerImage*>(layer);
|
||||
|
||||
// Displace all cels in '>=frame' to the next frame.
|
||||
for (FrameNumber c=sprite->getLastFrame(); c>=frame; --c) {
|
||||
Cel* cel = static_cast<LayerImage*>(layer)->getCel(c);
|
||||
Cel* cel = imglayer->getCel(c);
|
||||
if (cel)
|
||||
setCelFramePosition(sprite, cel, cel->getFrame().next());
|
||||
setCelFramePosition(imglayer, cel, cel->getFrame().next());
|
||||
}
|
||||
|
||||
copyPreviousFrame(layer, frame);
|
||||
if (fromFrame >= frame)
|
||||
fromFrame = fromFrame.next();
|
||||
|
||||
copyCel(sprite, imglayer, imglayer, fromFrame, frame, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case OBJECT_LAYER_FOLDER: {
|
||||
LayerIterator it = static_cast<LayerFolder*>(layer)->getLayerBegin();
|
||||
LayerIterator end = static_cast<LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
for (; it != end; ++it)
|
||||
addFrameForLayer(*it, frame);
|
||||
copyFrameForLayer(*it, fromFrame, frame);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentApi::copyPreviousFrame(Layer* layer, FrameNumber frame)
|
||||
{
|
||||
ASSERT(layer);
|
||||
ASSERT(frame >= 0);
|
||||
|
||||
Sprite* sprite = layer->getSprite();
|
||||
|
||||
// create a copy of the previous cel
|
||||
Cel* src_cel = static_cast<LayerImage*>(layer)->getCel(frame.previous());
|
||||
Image* src_image = src_cel ? sprite->getStock()->getImage(src_cel->getImage()):
|
||||
NULL;
|
||||
|
||||
// nothing to copy, it will be a transparent cel
|
||||
if (!src_image)
|
||||
return;
|
||||
|
||||
// copy the image
|
||||
Image* dst_image = Image::createCopy(src_image);
|
||||
int image_index = addImageInStock(sprite, dst_image);
|
||||
|
||||
// create the new cel
|
||||
Cel* dst_cel = new Cel(frame, image_index);
|
||||
if (src_cel) { // copy the data from the previous cel
|
||||
dst_cel->setPosition(src_cel->getX(), src_cel->getY());
|
||||
dst_cel->setOpacity(src_cel->getOpacity());
|
||||
}
|
||||
|
||||
// add the cel in the layer
|
||||
addCel(static_cast<LayerImage*>(layer), dst_cel);
|
||||
}
|
||||
|
||||
void DocumentApi::removeFrame(Sprite* sprite, FrameNumber frame)
|
||||
{
|
||||
ASSERT(frame >= 0);
|
||||
@ -325,14 +304,16 @@ void DocumentApi::removeFrameOfLayer(Layer* layer, FrameNumber frame)
|
||||
|
||||
switch (layer->type()) {
|
||||
|
||||
case OBJECT_LAYER_IMAGE:
|
||||
if (Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame))
|
||||
removeCel(static_cast<LayerImage*>(layer), cel);
|
||||
case OBJECT_LAYER_IMAGE: {
|
||||
LayerImage* imglayer = static_cast<LayerImage*>(layer);
|
||||
if (Cel* cel = imglayer->getCel(frame))
|
||||
removeCel(imglayer, cel);
|
||||
|
||||
for (++frame; frame<sprite->getTotalFrames(); ++frame)
|
||||
if (Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame))
|
||||
setCelFramePosition(sprite, cel, cel->getFrame().previous());
|
||||
if (Cel* cel = imglayer->getCel(frame))
|
||||
setCelFramePosition(imglayer, cel, cel->getFrame().previous());
|
||||
break;
|
||||
}
|
||||
|
||||
case OBJECT_LAYER_FOLDER: {
|
||||
LayerIterator it = static_cast<LayerFolder*>(layer)->getLayerBegin();
|
||||
@ -398,7 +379,7 @@ void DocumentApi::setFrameRangeDuration(Sprite* sprite, FrameNumber from, FrameN
|
||||
sprite->setFrameRangeDuration(from, to, msecs);
|
||||
}
|
||||
|
||||
void DocumentApi::moveFrameBefore(Sprite* sprite, FrameNumber frame, FrameNumber beforeFrame)
|
||||
void DocumentApi::moveFrame(Sprite* sprite, FrameNumber frame, FrameNumber beforeFrame)
|
||||
{
|
||||
if (frame != beforeFrame &&
|
||||
frame >= 0 &&
|
||||
@ -424,47 +405,53 @@ void DocumentApi::moveFrameBefore(Sprite* sprite, FrameNumber frame, FrameNumber
|
||||
}
|
||||
|
||||
// change the cels of position...
|
||||
moveFrameBeforeLayer(sprite->getFolder(), frame, beforeFrame);
|
||||
moveFrameLayer(sprite->getFolder(), frame, beforeFrame);
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentApi::moveFrameBeforeLayer(Layer* layer, FrameNumber frame, FrameNumber beforeFrame)
|
||||
void DocumentApi::moveFrameLayer(Layer* layer, FrameNumber frame, FrameNumber beforeFrame)
|
||||
{
|
||||
ASSERT(layer);
|
||||
|
||||
switch (layer->type()) {
|
||||
|
||||
case OBJECT_LAYER_IMAGE: {
|
||||
CelIterator it = ((LayerImage*)layer)->getCelBegin();
|
||||
CelIterator end = ((LayerImage*)layer)->getCelEnd();
|
||||
LayerImage* imglayer = static_cast<LayerImage*>(layer);
|
||||
|
||||
CelList cels;
|
||||
imglayer->getCels(cels);
|
||||
|
||||
CelIterator it = cels.begin();
|
||||
CelIterator end = cels.end();
|
||||
|
||||
for (; it != end; ++it) {
|
||||
Cel* cel = *it;
|
||||
FrameNumber newFrame = cel->getFrame();
|
||||
FrameNumber celFrame = cel->getFrame();
|
||||
FrameNumber newFrame = celFrame;
|
||||
|
||||
// moving the frame to the future
|
||||
if (frame < beforeFrame) {
|
||||
if (cel->getFrame() == frame) {
|
||||
if (celFrame == frame) {
|
||||
newFrame = beforeFrame.previous();
|
||||
}
|
||||
else if (cel->getFrame() > frame &&
|
||||
cel->getFrame() < beforeFrame) {
|
||||
else if (celFrame > frame &&
|
||||
celFrame < beforeFrame) {
|
||||
--newFrame;
|
||||
}
|
||||
}
|
||||
// moving the frame to the past
|
||||
else if (beforeFrame < frame) {
|
||||
if (cel->getFrame() == frame) {
|
||||
if (celFrame == frame) {
|
||||
newFrame = beforeFrame;
|
||||
}
|
||||
else if (cel->getFrame() >= beforeFrame &&
|
||||
cel->getFrame() < frame) {
|
||||
else if (celFrame >= beforeFrame &&
|
||||
celFrame < frame) {
|
||||
++newFrame;
|
||||
}
|
||||
}
|
||||
|
||||
if (cel->getFrame() != newFrame)
|
||||
setCelFramePosition(layer->getSprite(), cel, newFrame);
|
||||
if (celFrame != newFrame)
|
||||
setCelFramePosition(imglayer, cel, newFrame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -474,7 +461,7 @@ void DocumentApi::moveFrameBeforeLayer(Layer* layer, FrameNumber frame, FrameNum
|
||||
LayerIterator end = static_cast<LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
for (; it != end; ++it)
|
||||
moveFrameBeforeLayer(*it, frame, beforeFrame);
|
||||
moveFrameLayer(*it, frame, beforeFrame);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -511,8 +498,8 @@ void DocumentApi::removeCel(LayerImage* layer, Cel* cel)
|
||||
ev.cel(cel);
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onRemoveCel, ev);
|
||||
|
||||
// find if the image that use the cel to remove, is used by
|
||||
// another cels
|
||||
// Find if the image that use the cel to remove, is used by another
|
||||
// cels.
|
||||
bool used = false;
|
||||
for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
|
||||
Cel* it = layer->getCel(frame);
|
||||
@ -522,8 +509,8 @@ void DocumentApi::removeCel(LayerImage* layer, Cel* cel)
|
||||
}
|
||||
}
|
||||
|
||||
// if the image is only used by this cel,
|
||||
// we can remove the image from the stock
|
||||
// If the image is only used by this cel, we can remove the image
|
||||
// from the stock.
|
||||
if (!used)
|
||||
removeImageFromStock(sprite, cel->getImage());
|
||||
|
||||
@ -531,25 +518,26 @@ void DocumentApi::removeCel(LayerImage* layer, Cel* cel)
|
||||
m_undoers->pushUndoer(new undoers::RemoveCel(getObjects(),
|
||||
layer, cel));
|
||||
|
||||
// remove the cel from the layer
|
||||
// Remove the cel from the layer.
|
||||
layer->removeCel(cel);
|
||||
|
||||
// and here we destroy the cel
|
||||
delete cel;
|
||||
}
|
||||
|
||||
void DocumentApi::setCelFramePosition(Sprite* sprite, Cel* cel, FrameNumber frame)
|
||||
void DocumentApi::setCelFramePosition(LayerImage* layer, Cel* cel, FrameNumber frame)
|
||||
{
|
||||
ASSERT(cel);
|
||||
ASSERT(frame >= 0);
|
||||
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::SetCelFrame(getObjects(), cel));
|
||||
m_undoers->pushUndoer(new undoers::SetCelFrame(getObjects(), layer, cel));
|
||||
|
||||
cel->setFrame(frame);
|
||||
layer->moveCel(cel, frame);
|
||||
|
||||
DocumentEvent ev(m_document);
|
||||
ev.sprite(sprite);
|
||||
ev.sprite(layer->getSprite());
|
||||
ev.layer(layer);
|
||||
ev.cel(cel);
|
||||
ev.frame(frame);
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onCelFrameChanged, ev);
|
||||
@ -570,7 +558,7 @@ void DocumentApi::setCelPosition(Sprite* sprite, Cel* cel, int x, int y)
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onCelPositionChanged, ev);
|
||||
}
|
||||
|
||||
void DocumentApi::cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h, int bgcolor)
|
||||
void DocumentApi::cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h, color_t bgcolor)
|
||||
{
|
||||
Image* cel_image = sprite->getStock()->getImage(cel->getImage());
|
||||
ASSERT(cel_image);
|
||||
@ -585,6 +573,142 @@ void DocumentApi::cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h,
|
||||
setCelPosition(sprite, cel, x, y);
|
||||
}
|
||||
|
||||
void DocumentApi::moveCel(Sprite* sprite,
|
||||
LayerImage* srcLayer, LayerImage* dstLayer,
|
||||
FrameNumber srcFrame, FrameNumber dstFrame,
|
||||
color_t bgcolor)
|
||||
{
|
||||
ASSERT(srcLayer != NULL);
|
||||
ASSERT(dstLayer != NULL);
|
||||
ASSERT(srcFrame >= 0 && srcFrame < sprite->getTotalFrames());
|
||||
ASSERT(dstFrame >= 0 && dstFrame < sprite->getTotalFrames());
|
||||
|
||||
if (srcLayer->isBackground()) {
|
||||
copyCel(sprite, srcLayer, dstLayer, srcFrame, dstFrame, bgcolor);
|
||||
return;
|
||||
}
|
||||
|
||||
Cel* srcCel = srcLayer->getCel(srcFrame);
|
||||
Cel* dstCel = dstLayer->getCel(dstFrame);
|
||||
|
||||
// Remove the dstCel (if it exists) because it must be replaced with
|
||||
// srcCel.
|
||||
if ((dstCel != NULL) && (!dstLayer->isBackground() || srcCel != NULL))
|
||||
removeCel(dstLayer, dstCel);
|
||||
|
||||
if (srcCel != NULL) {
|
||||
// Move the cel in the same layer.
|
||||
if (srcLayer == dstLayer) {
|
||||
setCelFramePosition(srcLayer, srcCel, dstFrame);
|
||||
}
|
||||
// Move the cel between different layers.
|
||||
else {
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::RemoveCel(getObjects(), srcLayer, srcCel));
|
||||
srcLayer->removeCel(srcCel);
|
||||
|
||||
srcCel->setFrame(dstFrame);
|
||||
|
||||
// If we are moving a cel from a transparent layer to the
|
||||
// background layer, we have to clear the background of the
|
||||
// image.
|
||||
if (!srcLayer->isBackground() &&
|
||||
dstLayer->isBackground()) {
|
||||
Image* srcImage = sprite->getStock()->getImage(srcCel->getImage());
|
||||
Image* dstImage = crop_image(srcImage,
|
||||
-srcCel->getX(),
|
||||
-srcCel->getY(),
|
||||
sprite->getWidth(),
|
||||
sprite->getHeight(), 0);
|
||||
|
||||
if (undoEnabled()) {
|
||||
m_undoers->pushUndoer(new undoers::ReplaceImage(getObjects(),
|
||||
sprite->getStock(), srcCel->getImage()));
|
||||
m_undoers->pushUndoer(new undoers::SetCelPosition(getObjects(), srcCel));
|
||||
m_undoers->pushUndoer(new undoers::SetCelOpacity(getObjects(), srcCel));
|
||||
}
|
||||
|
||||
clear_image(dstImage, bgcolor);
|
||||
composite_image(dstImage, srcImage, srcCel->getX(), srcCel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
|
||||
srcCel->setPosition(0, 0);
|
||||
srcCel->setOpacity(255);
|
||||
|
||||
sprite->getStock()->replaceImage(srcCel->getImage(), dstImage);
|
||||
delete srcImage;
|
||||
}
|
||||
|
||||
addCel(dstLayer, srcCel);
|
||||
}
|
||||
}
|
||||
|
||||
m_document->notifyCelMoved(srcLayer, srcFrame, dstLayer, dstFrame);
|
||||
}
|
||||
|
||||
void DocumentApi::copyCel(Sprite* sprite,
|
||||
LayerImage* srcLayer, LayerImage* dstLayer,
|
||||
FrameNumber srcFrame, FrameNumber dstFrame,
|
||||
color_t bgcolor)
|
||||
{
|
||||
ASSERT(srcLayer != NULL);
|
||||
ASSERT(dstLayer != NULL);
|
||||
ASSERT(srcFrame >= 0 && srcFrame < sprite->getTotalFrames());
|
||||
ASSERT(dstFrame >= 0 && dstFrame < sprite->getTotalFrames());
|
||||
|
||||
Cel* srcCel = srcLayer->getCel(srcFrame);
|
||||
Cel* dstCel = dstLayer->getCel(dstFrame);
|
||||
|
||||
// Remove the 'dstCel' (if it exists) because it must be replaced
|
||||
// with 'srcCel'
|
||||
if ((dstCel != NULL) && (!dstLayer->isBackground() || srcCel != NULL))
|
||||
removeCel(dstLayer, dstCel);
|
||||
|
||||
// Move the cel in the same layer.
|
||||
if (srcCel != NULL) {
|
||||
Image *srcImage = sprite->getStock()->getImage(srcCel->getImage());
|
||||
Image *dstImage;
|
||||
int dstCel_x;
|
||||
int dstCel_y;
|
||||
int dstCel_opacity;
|
||||
|
||||
// If we are moving a cel from a transparent layer to the
|
||||
// background layer, we have to clear the background of the image.
|
||||
if (!srcLayer->isBackground() &&
|
||||
dstLayer->isBackground()) {
|
||||
dstImage = crop_image(srcImage,
|
||||
-srcCel->getX(),
|
||||
-srcCel->getY(),
|
||||
sprite->getWidth(),
|
||||
sprite->getHeight(), 0);
|
||||
|
||||
clear_image(dstImage, bgcolor);
|
||||
composite_image(dstImage, srcImage, srcCel->getX(), srcCel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
|
||||
dstCel_x = 0;
|
||||
dstCel_y = 0;
|
||||
dstCel_opacity = 255;
|
||||
}
|
||||
else {
|
||||
dstImage = Image::createCopy(srcImage);
|
||||
dstCel_x = srcCel->getX();
|
||||
dstCel_y = srcCel->getY();
|
||||
dstCel_opacity = srcCel->getOpacity();
|
||||
}
|
||||
|
||||
// Add the image in the stock
|
||||
int image_index = addImageInStock(sprite, dstImage);
|
||||
|
||||
// Create the new cel
|
||||
dstCel = new Cel(dstFrame, image_index);
|
||||
dstCel->setPosition(dstCel_x, dstCel_y);
|
||||
dstCel->setOpacity(dstCel_opacity);
|
||||
|
||||
addCel(dstLayer, dstCel);
|
||||
}
|
||||
|
||||
m_document->notifyCelCopied(srcLayer, srcFrame, dstLayer, dstFrame);
|
||||
}
|
||||
|
||||
LayerImage* DocumentApi::newLayer(Sprite* sprite)
|
||||
{
|
||||
LayerImage* layer = new LayerImage(sprite);
|
||||
@ -672,13 +796,13 @@ void DocumentApi::restackLayerAfter(Layer* layer, Layer* afterThis)
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onLayerRestacked, ev);
|
||||
}
|
||||
|
||||
void DocumentApi::cropLayer(Layer* layer, int x, int y, int w, int h, int bgcolor)
|
||||
void DocumentApi::cropLayer(Layer* layer, int x, int y, int w, int h, color_t bgcolor)
|
||||
{
|
||||
if (!layer->isImage())
|
||||
return;
|
||||
|
||||
if (!layer->isBackground())
|
||||
bgcolor = 0;
|
||||
bgcolor = 0; // TODO use proper mask color
|
||||
|
||||
Sprite* sprite = layer->getSprite();
|
||||
CelIterator it = ((LayerImage*)layer)->getCelBegin();
|
||||
@ -713,7 +837,7 @@ void DocumentApi::displaceLayers(Layer* layer, int dx, int dy)
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentApi::backgroundFromLayer(LayerImage* layer, int bgcolor)
|
||||
void DocumentApi::backgroundFromLayer(LayerImage* layer, color_t bgcolor)
|
||||
{
|
||||
ASSERT(layer);
|
||||
ASSERT(layer->isImage());
|
||||
@ -806,7 +930,7 @@ void DocumentApi::layerFromBackground(Layer* layer)
|
||||
layer->setName("Layer 0");
|
||||
}
|
||||
|
||||
void DocumentApi::flattenLayers(Sprite* sprite, int bgcolor)
|
||||
void DocumentApi::flattenLayers(Sprite* sprite, color_t bgcolor)
|
||||
{
|
||||
Image* cel_image;
|
||||
Cel* cel;
|
||||
@ -873,6 +997,20 @@ void DocumentApi::flattenLayers(Sprite* sprite, int bgcolor)
|
||||
removeLayer(*it);
|
||||
}
|
||||
|
||||
void DocumentApi::duplicateLayer(Layer* sourceLayer, Layer* afterLayer)
|
||||
{
|
||||
base::UniquePtr<LayerImage> newLayerPtr(new LayerImage(sourceLayer->getSprite()));
|
||||
|
||||
m_document->copyLayerContent(sourceLayer, m_document, newLayerPtr);
|
||||
|
||||
newLayerPtr->setName(newLayerPtr->getName() + " Copy");
|
||||
|
||||
addLayer(sourceLayer->getParent(), newLayerPtr, afterLayer);
|
||||
|
||||
// Release the pointer as it is owned by the sprite now.
|
||||
newLayerPtr.release();
|
||||
}
|
||||
|
||||
// Adds a new image in the stock. Returns the image index in the
|
||||
// stock.
|
||||
int DocumentApi::addImageInStock(Sprite* sprite, Image* image)
|
||||
@ -930,7 +1068,7 @@ Image* DocumentApi::getCelImage(Sprite* sprite, Cel* cel)
|
||||
}
|
||||
|
||||
// Clears the mask region in the current sprite with the specified background color.
|
||||
void DocumentApi::clearMask(Layer* layer, Cel* cel, int bgcolor)
|
||||
void DocumentApi::clearMask(Layer* layer, Cel* cel, color_t bgcolor)
|
||||
{
|
||||
Image* image = getCelImage(layer->getSprite(), cel);
|
||||
if (!image)
|
||||
@ -1007,7 +1145,7 @@ void DocumentApi::flipImage(Image* image, const gfx::Rect& bounds,
|
||||
raster::algorithm::flip_image(image, bounds, flipType);
|
||||
}
|
||||
|
||||
void DocumentApi::flipImageWithMask(Image* image, const Mask* mask, raster::algorithm::FlipType flipType, int bgcolor)
|
||||
void DocumentApi::flipImageWithMask(Image* image, const Mask* mask, raster::algorithm::FlipType flipType, color_t bgcolor)
|
||||
{
|
||||
base::UniquePtr<Image> flippedImage((Image::createCopy(image)));
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "gfx/rect.h"
|
||||
#include "raster/algorithm/flip_type.h"
|
||||
#include "raster/color.h"
|
||||
#include "raster/dithering_method.h"
|
||||
#include "raster/frame_number.h"
|
||||
#include "raster/pixel_format.h"
|
||||
@ -61,24 +62,30 @@ namespace app {
|
||||
|
||||
// Sprite API
|
||||
void setSpriteSize(Sprite* sprite, int w, int h);
|
||||
void cropSprite(Sprite* sprite, const gfx::Rect& bounds, int bgcolor);
|
||||
void trimSprite(Sprite* sprite, int bgcolor);
|
||||
void cropSprite(Sprite* sprite, const gfx::Rect& bounds, color_t bgcolor);
|
||||
void trimSprite(Sprite* sprite, color_t bgcolor);
|
||||
void setPixelFormat(Sprite* sprite, PixelFormat newFormat, DitheringMethod dithering_method);
|
||||
|
||||
// Frames API
|
||||
void addFrame(Sprite* sprite, FrameNumber newFrame);
|
||||
void copyFrame(Sprite* sprite, FrameNumber fromFrame, FrameNumber newFrame);
|
||||
void removeFrame(Sprite* sprite, FrameNumber frame);
|
||||
void setTotalFrames(Sprite* sprite, FrameNumber frames);
|
||||
void setFrameDuration(Sprite* sprite, FrameNumber frame, int msecs);
|
||||
void setFrameRangeDuration(Sprite* sprite, FrameNumber from, FrameNumber to, int msecs);
|
||||
void moveFrameBefore(Sprite* sprite, FrameNumber frame, FrameNumber beforeFrame);
|
||||
void moveFrame(Sprite* sprite, FrameNumber frame, FrameNumber beforeFrame);
|
||||
|
||||
// Cels API
|
||||
void addCel(LayerImage* layer, Cel* cel);
|
||||
void removeCel(LayerImage* layer, Cel* cel);
|
||||
void setCelFramePosition(Sprite* sprite, Cel* cel, FrameNumber frame);
|
||||
void setCelPosition(Sprite* sprite, Cel* cel, int x, int y);
|
||||
void cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h, int bgcolor);
|
||||
void cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h, color_t bgcolor);
|
||||
void moveCel(Sprite* sprite,
|
||||
LayerImage* srcLayer, LayerImage* dstLayer,
|
||||
FrameNumber srcFrame, FrameNumber dstFrame, color_t bgcolor);
|
||||
void copyCel(Sprite* sprite,
|
||||
LayerImage* srcLayer, LayerImage* dstLayer,
|
||||
FrameNumber srcFrame, FrameNumber dstFrame, color_t bgcolor);
|
||||
|
||||
// Layers API
|
||||
LayerImage* newLayer(Sprite* sprite);
|
||||
@ -86,11 +93,12 @@ namespace app {
|
||||
void addLayer(LayerFolder* folder, Layer* newLayer, Layer* afterThis);
|
||||
void removeLayer(Layer* layer);
|
||||
void restackLayerAfter(Layer* layer, Layer* afterThis);
|
||||
void cropLayer(Layer* layer, int x, int y, int w, int h, int bgcolor);
|
||||
void cropLayer(Layer* layer, int x, int y, int w, int h, color_t bgcolor);
|
||||
void displaceLayers(Layer* layer, int dx, int dy);
|
||||
void backgroundFromLayer(LayerImage* layer, int bgcolor);
|
||||
void backgroundFromLayer(LayerImage* layer, color_t bgcolor);
|
||||
void layerFromBackground(Layer* layer);
|
||||
void flattenLayers(Sprite* sprite, int bgcolor);
|
||||
void flattenLayers(Sprite* sprite, color_t bgcolor);
|
||||
void duplicateLayer(Layer* sourceLayer, Layer* afterLayer);
|
||||
|
||||
// Images stock API
|
||||
int addImageInStock(Sprite* sprite, Image* image);
|
||||
@ -99,9 +107,9 @@ namespace app {
|
||||
|
||||
// Image API
|
||||
Image* getCelImage(Sprite* sprite, Cel* cel);
|
||||
void clearMask(Layer* layer, Cel* cel, int bgcolor);
|
||||
void clearMask(Layer* layer, Cel* cel, color_t bgcolor);
|
||||
void flipImage(Image* image, const gfx::Rect& bounds, raster::algorithm::FlipType flipType);
|
||||
void flipImageWithMask(Image* image, const Mask* mask, raster::algorithm::FlipType flipType, int bgcolor);
|
||||
void flipImageWithMask(Image* image, const Mask* mask, raster::algorithm::FlipType flipType, color_t bgcolor);
|
||||
void pasteImage(Sprite* sprite, Cel* cel, const Image* src_image, int x, int y, int opacity);
|
||||
|
||||
// Mask API
|
||||
@ -114,10 +122,10 @@ namespace app {
|
||||
|
||||
private:
|
||||
undo::ObjectsContainer* getObjects() const;
|
||||
void addFrameForLayer(Layer* layer, FrameNumber frame);
|
||||
void setCelFramePosition(LayerImage* layer, Cel* cel, FrameNumber frame);
|
||||
void copyFrameForLayer(Layer* layer, FrameNumber fromFrame, FrameNumber frame);
|
||||
void removeFrameOfLayer(Layer* layer, FrameNumber frame);
|
||||
void copyPreviousFrame(Layer* layer, FrameNumber frame);
|
||||
void moveFrameBeforeLayer(Layer* layer, FrameNumber frame, FrameNumber beforeFrame);
|
||||
void moveFrameLayer(Layer* layer, FrameNumber frame, FrameNumber beforeFrame);
|
||||
void configureLayerAsBackground(LayerImage* layer);
|
||||
bool undoEnabled();
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "app/ui/timeline.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/app_menus.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/commands/commands.h"
|
||||
@ -43,7 +44,6 @@
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/undo_transaction.h"
|
||||
#include "app/util/celmove.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/memory.h"
|
||||
#include "gfx/point.h"
|
||||
@ -103,6 +103,8 @@ static const char* kTimelinePaddingBl = "timeline_padding_bl";
|
||||
static const char* kTimelinePaddingBr = "timeline_padding_br";
|
||||
static const char* kTimelineSelectedCelStyle = "timeline_selected_cel";
|
||||
static const char* kTimelineRangeOutlineStyle = "timeline_range_outline";
|
||||
static const char* kTimelineDropLayerDecoStyle = "timeline_drop_layer_deco";
|
||||
static const char* kTimelineDropFrameDecoStyle = "timeline_drop_frame_deco";
|
||||
|
||||
static const char* kTimelineActiveColor = "timeline_active";
|
||||
|
||||
@ -146,6 +148,8 @@ Timeline::Timeline()
|
||||
, m_timelinePaddingBrStyle(get_style(kTimelinePaddingBr))
|
||||
, m_timelineSelectedCelStyle(get_style(kTimelineSelectedCelStyle))
|
||||
, m_timelineRangeOutlineStyle(get_style(kTimelineRangeOutlineStyle))
|
||||
, m_timelineDropLayerDecoStyle(get_style(kTimelineDropLayerDecoStyle))
|
||||
, m_timelineDropFrameDecoStyle(get_style(kTimelineDropFrameDecoStyle))
|
||||
, m_context(UIContext::instance())
|
||||
, m_editor(NULL)
|
||||
, m_document(NULL)
|
||||
@ -230,7 +234,8 @@ void Timeline::detachDocument()
|
||||
|
||||
bool Timeline::isMovingCel() const
|
||||
{
|
||||
return (m_state == Timeline::STATE_MOVING_CEL);
|
||||
return (m_state == Timeline::STATE_MOVING_RANGE &&
|
||||
m_range.type() == Range::kCels);
|
||||
}
|
||||
|
||||
void Timeline::setLayer(Layer* layer)
|
||||
@ -286,7 +291,6 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
m_clk_frame = m_hot_frame;
|
||||
|
||||
captureMouse();
|
||||
m_oldPos = static_cast<MouseMessage*>(msg)->position();
|
||||
|
||||
switch (m_hot_part) {
|
||||
case A_PART_SEPARATOR:
|
||||
@ -311,12 +315,9 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
|
||||
if (selectFrame) {
|
||||
setFrame(m_clk_frame);
|
||||
if (msg->ctrlPressed())
|
||||
m_state = STATE_MOVING_FRAME;
|
||||
else {
|
||||
m_state = STATE_SELECTING_FRAMES;
|
||||
m_range.startRange(getLayerIndex(m_layer), m_clk_frame, Range::Frames);
|
||||
}
|
||||
|
||||
m_state = STATE_SELECTING_FRAMES;
|
||||
m_range.startRange(getLayerIndex(m_layer), m_clk_frame, Range::kFrames);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -339,20 +340,8 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
showCel(m_clk_layer, m_frame);
|
||||
|
||||
if (selectLayer) {
|
||||
bool startRange = false;
|
||||
|
||||
if (msg->ctrlPressed()) {
|
||||
m_state = STATE_MOVING_LAYER;
|
||||
if (!m_range.inRange(m_clk_layer))
|
||||
startRange = true;
|
||||
}
|
||||
else {
|
||||
m_state = STATE_SELECTING_LAYERS;
|
||||
startRange = true;
|
||||
}
|
||||
|
||||
if (startRange)
|
||||
m_range.startRange(m_clk_layer, m_frame, Range::Layers);
|
||||
m_state = STATE_SELECTING_LAYERS;
|
||||
m_range.startRange(m_clk_layer, m_frame, Range::kLayers);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -380,16 +369,15 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
// Change the scroll to show the new selected cel.
|
||||
showCel(m_clk_layer, m_frame);
|
||||
|
||||
if (msg->ctrlPressed())
|
||||
m_state = STATE_MOVING_CEL;
|
||||
else {
|
||||
m_state = STATE_SELECTING_CELS;
|
||||
if (selectCel)
|
||||
m_range.startRange(m_clk_layer, m_clk_frame, Range::Cels);
|
||||
invalidate();
|
||||
}
|
||||
m_state = STATE_SELECTING_CELS;
|
||||
if (selectCel)
|
||||
m_range.startRange(m_clk_layer, m_clk_frame, Range::kCels);
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
case A_PART_RANGE_OUTLINE:
|
||||
m_state = STATE_MOVING_RANGE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Redraw the new clicked part (header, layer or cel).
|
||||
@ -607,29 +595,9 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
if (popup_menu != NULL) {
|
||||
gfx::Point mousePos = mouseMsg->position();
|
||||
popup_menu->showPopup(mousePos.x, mousePos.y);
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// Show the frame's properties dialog.
|
||||
else if (mouseMsg->left()) {
|
||||
const ContextReader reader(m_context);
|
||||
|
||||
if (m_hot_frame >= 0 &&
|
||||
m_hot_frame < m_sprite->getTotalFrames() &&
|
||||
m_hot_frame != m_clk_frame+1) {
|
||||
{
|
||||
ContextWriter writer(reader);
|
||||
UndoTransaction undoTransaction(m_context, "Move Frame");
|
||||
m_document->getApi().moveFrameBefore(writer.sprite(), m_clk_frame, m_hot_frame);
|
||||
undoTransaction.commit();
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case A_PART_LAYER_TEXT:
|
||||
// Show the layer pop-up menu.
|
||||
@ -639,56 +607,9 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
if (popup_menu != NULL) {
|
||||
gfx::Point mousePos = mouseMsg->position();
|
||||
popup_menu->showPopup(mousePos.x, mousePos.y);
|
||||
|
||||
invalidate();
|
||||
regenerateLayers();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Move a layer.
|
||||
else if (m_state == STATE_MOVING_LAYER) {
|
||||
if (m_hot_layer >= 0
|
||||
&& m_hot_layer < (int)m_layers.size()
|
||||
&& !isLayerActive(m_hot_layer)) {
|
||||
|
||||
if (m_layers[m_clk_layer]->isBackground()) {
|
||||
Alert::show(PACKAGE "<<You can't move the `Background' layer.||&OK");
|
||||
break;
|
||||
}
|
||||
|
||||
// Move the clicked-layer after the hot-layer.
|
||||
try {
|
||||
const ContextReader reader(m_context);
|
||||
ContextWriter writer(reader);
|
||||
|
||||
UndoTransaction undoTransaction(m_context, "Move Layer");
|
||||
|
||||
Layer* firstLayer = m_layers[m_range.layerBegin()];
|
||||
Layer* lastLayer = m_layers[m_range.layerEnd()];
|
||||
|
||||
for (int i = m_range.layerBegin(); i <= m_range.layerEnd(); ++i) {
|
||||
m_document->getApi().restackLayerAfter(
|
||||
m_layers[i], m_layers[m_hot_layer]);
|
||||
}
|
||||
|
||||
undoTransaction.commit();
|
||||
|
||||
// Select the new layer.
|
||||
setLayer(m_layers[m_clk_layer]);
|
||||
|
||||
regenerateLayers();
|
||||
|
||||
m_range.startRange(getLayerIndex(firstLayer), m_frame, m_range.type());
|
||||
m_range.endRange(getLayerIndex(lastLayer), m_frame);
|
||||
}
|
||||
catch (LockedDocumentException& e) {
|
||||
Console::showException(e);
|
||||
regenerateLayers();
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case A_PART_LAYER_EYE_ICON:
|
||||
// Hide/show layer.
|
||||
@ -714,49 +635,29 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
}
|
||||
break;
|
||||
case A_PART_CEL: {
|
||||
if (m_state == STATE_MOVING_CEL) {
|
||||
Layer* src_layer = m_layers[m_clk_layer];
|
||||
Layer* dst_layer = m_layers[m_hot_layer];
|
||||
FrameNumber src_frame = m_clk_frame;
|
||||
FrameNumber dst_frame = m_hot_frame;
|
||||
|
||||
if (src_layer == dst_layer &&
|
||||
src_frame == dst_frame)
|
||||
break;
|
||||
|
||||
set_frame_to_handle(src_layer, src_frame, dst_layer, dst_frame);
|
||||
}
|
||||
|
||||
// Show the cel pop-up menu.
|
||||
if (mouseMsg->right()) {
|
||||
Menu* popup_menu = (m_state == STATE_MOVING_CEL) ?
|
||||
AppMenus::instance()->getCelMovementPopupMenu():
|
||||
AppMenus::instance()->getCelPopupMenu();
|
||||
Menu* popup_menu =
|
||||
(m_state == STATE_MOVING_RANGE &&
|
||||
m_range.type() == Range::kCels) ?
|
||||
AppMenus::instance()->getCelMovementPopupMenu():
|
||||
AppMenus::instance()->getCelPopupMenu();
|
||||
|
||||
if (popup_menu != NULL) {
|
||||
gfx::Point mousePos = mouseMsg->position();
|
||||
popup_menu->showPopup(mousePos.x, mousePos.y);
|
||||
|
||||
regenerateLayers();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
// Move the cel.
|
||||
else if (mouseMsg->left()) {
|
||||
if (m_state == STATE_MOVING_CEL) {
|
||||
{
|
||||
const ContextReader reader(m_context);
|
||||
ContextWriter writer(reader);
|
||||
move_cel(writer);
|
||||
}
|
||||
regenerateLayers();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mouseMsg->left() && m_state == STATE_MOVING_RANGE) {
|
||||
dropRange(mouseMsg->ctrlPressed() ?
|
||||
Timeline::kCopy:
|
||||
Timeline::kMove);
|
||||
}
|
||||
|
||||
// Clean the clicked-part & redraw the hot-part.
|
||||
cleanClk();
|
||||
|
||||
@ -937,7 +838,6 @@ void Timeline::onPaint(ui::PaintEvent& ev)
|
||||
// Draw every visible cel for each layer.
|
||||
for (frame=first_frame; frame<=last_frame; ++frame) {
|
||||
Cel* cel = (layerPtr->isImage() && it != end && (*it)->getFrame() == frame ? *it: NULL);
|
||||
|
||||
drawCel(g, layer, frame, cel);
|
||||
|
||||
if (cel)
|
||||
@ -1060,42 +960,19 @@ void Timeline::onLayerChanged(Editor* editor)
|
||||
void Timeline::setCursor(int x, int y)
|
||||
{
|
||||
int mx = x - getBounds().x;
|
||||
//int my = y - getBounds().y;
|
||||
|
||||
// Scrolling.
|
||||
if (m_state == STATE_SCROLLING || key[KEY_SPACE]) {
|
||||
jmouse_set_cursor(kScrollCursor);
|
||||
}
|
||||
// Moving a frame.
|
||||
else if (m_state == STATE_MOVING_FRAME &&
|
||||
m_clk_part == A_PART_HEADER_FRAME &&
|
||||
m_hot_part == A_PART_HEADER_FRAME &&
|
||||
m_clk_frame != m_hot_frame) {
|
||||
jmouse_set_cursor(kMoveCursor);
|
||||
}
|
||||
// Moving a layer.
|
||||
else if (m_state == STATE_MOVING_LAYER &&
|
||||
m_clk_part == A_PART_LAYER_TEXT &&
|
||||
m_hot_part == A_PART_LAYER_TEXT &&
|
||||
m_clk_layer != m_hot_layer) {
|
||||
if (m_layers[m_clk_layer]->isBackground())
|
||||
jmouse_set_cursor(kForbiddenCursor);
|
||||
// Moving.
|
||||
else if (m_state == STATE_MOVING_RANGE) {
|
||||
if (key[KEY_LCONTROL] || key[KEY_RCONTROL])
|
||||
jmouse_set_cursor(kArrowPlusCursor);
|
||||
else
|
||||
jmouse_set_cursor(kMoveCursor);
|
||||
}
|
||||
// Moving a cel.
|
||||
else if (m_state == STATE_MOVING_CEL &&
|
||||
m_clk_part == A_PART_CEL &&
|
||||
m_hot_part == A_PART_CEL &&
|
||||
(m_clk_frame != m_hot_frame ||
|
||||
m_clk_layer != m_hot_layer)) {
|
||||
jmouse_set_cursor(kMoveCursor);
|
||||
}
|
||||
// Normal state.
|
||||
else if (mx > m_separator_x-2 && mx < m_separator_x+2) {
|
||||
// Is the mouse in the separator.
|
||||
jmouse_set_cursor(kSizeLCursor);
|
||||
}
|
||||
else if (m_hot_part == A_PART_HEADER_ONIONSKIN_RANGE_LEFT
|
||||
|| m_state == STATE_MOVING_ONIONSKIN_RANGE_LEFT) {
|
||||
jmouse_set_cursor(kSizeLCursor);
|
||||
@ -1107,6 +984,10 @@ void Timeline::setCursor(int x, int y)
|
||||
else if (m_hot_part == A_PART_RANGE_OUTLINE) {
|
||||
jmouse_set_cursor(kMoveCursor);
|
||||
}
|
||||
else if (mx > m_separator_x-2 && mx < m_separator_x+2) {
|
||||
// Is the mouse in the separator.
|
||||
jmouse_set_cursor(kSizeLCursor);
|
||||
}
|
||||
else {
|
||||
jmouse_set_cursor(kArrowCursor);
|
||||
}
|
||||
@ -1244,10 +1125,8 @@ void Timeline::drawCel(ui::Graphics* g, int layer_index, FrameNumber frame, Cel*
|
||||
if (!clip)
|
||||
return;
|
||||
|
||||
if (m_range.inRange(layer_index, frame)
|
||||
|| (isLayerActive(layer_index) && isFrameActive(frame))) {
|
||||
if (layer_index == getLayerIndex(m_layer) && frame == m_frame)
|
||||
drawPart(g, bounds, NULL, m_timelineSelectedCelStyle, false, false, true);
|
||||
}
|
||||
else
|
||||
drawPart(g, bounds, NULL, m_timelineBoxStyle, is_active, is_hover);
|
||||
|
||||
@ -1284,13 +1163,52 @@ void Timeline::drawCel(ui::Graphics* g, int layer_index, FrameNumber frame, Cel*
|
||||
|
||||
void Timeline::drawRangeOutline(ui::Graphics* g)
|
||||
{
|
||||
gfx::Rect bounds = getPartBounds(A_PART_RANGE_OUTLINE);
|
||||
gfx::Rect clipBounds;
|
||||
switch (m_range.type()) {
|
||||
case Range::kCels: clipBounds = getCelsBounds(); break;
|
||||
case Range::kFrames: clipBounds = getFrameHeadersBounds(); break;
|
||||
case Range::kLayers: clipBounds = getLayerHeadersBounds(); break;
|
||||
}
|
||||
IntersectClip clip(g, clipBounds);
|
||||
if (!clip)
|
||||
return;
|
||||
|
||||
Style::State state;
|
||||
if (m_range.enabled()) state += Style::active();
|
||||
if (m_hot_part == A_PART_RANGE_OUTLINE) state += Style::hover();
|
||||
|
||||
gfx::Rect bounds = getPartBounds(A_PART_RANGE_OUTLINE);
|
||||
m_timelineRangeOutlineStyle->paint(g, bounds, NULL, state);
|
||||
|
||||
Range drop = getDropRange();
|
||||
switch (drop.type()) {
|
||||
|
||||
case Range::kCels:
|
||||
bounds =
|
||||
getPartBounds(A_PART_CEL, drop.layerBegin(), drop.frameBegin()).createUnion(
|
||||
getPartBounds(A_PART_CEL, drop.layerEnd(), drop.frameEnd()))
|
||||
// TODO theme specific
|
||||
.enlarge(2*jguiscale());
|
||||
|
||||
m_timelineRangeOutlineStyle->paint(g, bounds, NULL, Style::active());
|
||||
break;
|
||||
|
||||
case Range::kFrames:
|
||||
bounds = getPartBounds(A_PART_HEADER_FRAME, 0, drop.frameBegin());
|
||||
bounds.w = 5 * jguiscale(); // TODO get height from the skin info
|
||||
bounds.x -= bounds.w/2;
|
||||
|
||||
m_timelineDropFrameDecoStyle->paint(g, bounds, NULL, Style::State());
|
||||
break;
|
||||
|
||||
case Range::kLayers:
|
||||
bounds = getPartBounds(A_PART_LAYER, drop.layerBegin());
|
||||
bounds.h = 5 * jguiscale(); // TODO get height from the skin info
|
||||
bounds.y -= bounds.h/2;
|
||||
|
||||
m_timelineDropLayerDecoStyle->paint(g, bounds, NULL, Style::State());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::drawPaddings(ui::Graphics* g)
|
||||
@ -1451,16 +1369,18 @@ gfx::Rect Timeline::getPartBounds(int part, int layer, FrameNumber frame) const
|
||||
|
||||
case A_PART_RANGE_OUTLINE:
|
||||
switch (m_range.type()) {
|
||||
case Range::None: break; // Return empty rectangle
|
||||
case Range::Cels:
|
||||
case Range::kNone: break; // Return empty rectangle
|
||||
case Range::kCels:
|
||||
return
|
||||
getPartBounds(A_PART_CEL, m_range.layerBegin(), m_range.frameBegin()).createUnion(
|
||||
getPartBounds(A_PART_CEL, m_range.layerEnd(), m_range.frameEnd())).enlarge(2*jguiscale());
|
||||
case Range::Frames:
|
||||
getPartBounds(A_PART_CEL, m_range.layerEnd(), m_range.frameEnd()));
|
||||
// TODO theme specific
|
||||
//.enlarge(2*jguiscale());
|
||||
case Range::kFrames:
|
||||
return
|
||||
getPartBounds(A_PART_HEADER_FRAME, 0, m_range.frameBegin()).createUnion(
|
||||
getPartBounds(A_PART_HEADER_FRAME, 0, m_range.frameEnd()));
|
||||
case Range::Layers:
|
||||
case Range::kLayers:
|
||||
return
|
||||
getPartBounds(A_PART_LAYER, m_range.layerBegin()).createUnion(
|
||||
getPartBounds(A_PART_LAYER, m_range.layerEnd()));
|
||||
@ -1499,23 +1419,26 @@ void Timeline::hotThis(int hot_part, int hot_layer, FrameNumber hot_frame)
|
||||
if (hot_part != m_hot_part ||
|
||||
hot_layer != m_hot_layer ||
|
||||
hot_frame != m_hot_frame) {
|
||||
// Clean the old 'hot' thing.
|
||||
invalidatePart(m_hot_part,
|
||||
m_hot_layer,
|
||||
m_hot_frame);
|
||||
// Invalidate the whole control.
|
||||
if (m_state == STATE_MOVING_RANGE ||
|
||||
hot_part == A_PART_RANGE_OUTLINE ||
|
||||
m_hot_part == A_PART_RANGE_OUTLINE) {
|
||||
invalidate();
|
||||
}
|
||||
// Invalidate the old and new 'hot' thing.
|
||||
else {
|
||||
invalidatePart(m_hot_part,
|
||||
m_hot_layer,
|
||||
m_hot_frame);
|
||||
invalidatePart(m_hot_part,
|
||||
m_hot_layer,
|
||||
m_hot_frame);
|
||||
}
|
||||
|
||||
// Draw the new 'hot' thing.
|
||||
m_hot_part = hot_part;
|
||||
m_hot_layer = hot_layer;
|
||||
m_hot_frame = hot_frame;
|
||||
invalidatePart(m_hot_part,
|
||||
m_hot_layer,
|
||||
m_hot_frame);
|
||||
|
||||
#if 0 // TODO remove these lines
|
||||
if (getPartBounds(hot_part, hot_layer, hot_frame).isEmpty())
|
||||
m_hot_part = A_PART_NOTHING;
|
||||
#endif
|
||||
|
||||
updateStatusBar();
|
||||
}
|
||||
@ -1699,6 +1622,279 @@ bool Timeline::isFrameActive(FrameNumber frame) const
|
||||
return m_range.inRange(frame);
|
||||
}
|
||||
|
||||
void Timeline::dropRange(DropOp op)
|
||||
{
|
||||
// "Do nothing" cases. The user drops in the same place. (We don't
|
||||
// even add the undo information.)
|
||||
Range drop = getDropRange();
|
||||
switch (drop.type()) {
|
||||
case Range::kCels:
|
||||
if (drop == m_range)
|
||||
return;
|
||||
break;
|
||||
case Range::kFrames:
|
||||
if (op == Timeline::kMove && drop.frameBegin() == m_range.frameBegin())
|
||||
return;
|
||||
break;
|
||||
case Range::kLayers:
|
||||
if (op == Timeline::kMove && drop.layerBegin() == m_range.layerBegin())
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
const char* undoLabel = NULL;
|
||||
switch (op) {
|
||||
case Timeline::kMove: undoLabel = "Move Range"; break;
|
||||
case Timeline::kCopy: undoLabel = "Copy Range"; break;
|
||||
}
|
||||
|
||||
const ContextReader reader(m_context);
|
||||
ContextWriter writer(reader);
|
||||
UndoTransaction undo(writer.context(), undoLabel, undo::ModifyDocument);
|
||||
int activeRelativeLayer = getLayerIndex(m_layer) - m_range.layerBegin();
|
||||
FrameNumber activeRelativeFrame = m_frame - m_range.frameBegin();
|
||||
|
||||
switch (drop.type()) {
|
||||
case Range::kCels: dropCels(op, drop); break;
|
||||
case Range::kFrames: dropFrames(op, drop); break;
|
||||
case Range::kLayers: dropLayers(op, drop); break;
|
||||
}
|
||||
|
||||
undo.commit();
|
||||
|
||||
regenerateLayers();
|
||||
|
||||
// Adjust "drop" range so we can select the same selected range that
|
||||
// the user had selected.
|
||||
switch (drop.type()) {
|
||||
|
||||
case Range::kFrames:
|
||||
if (op == Timeline::kMove && m_range.frameBegin() < drop.frameBegin()) {
|
||||
drop.displace(0, FrameNumber(-m_range.frames()));
|
||||
}
|
||||
drop.setFrames(m_range.frames());
|
||||
break;
|
||||
|
||||
case Range::kLayers:
|
||||
if (op == Timeline::kMove && m_range.layerBegin() < drop.layerBegin()) {
|
||||
drop.displace(-m_range.layers(), FrameNumber(0));
|
||||
}
|
||||
drop.setLayers(m_range.layers());
|
||||
break;
|
||||
}
|
||||
|
||||
setLayer(m_layers[drop.layerBegin() + activeRelativeLayer]);
|
||||
setFrame(drop.frameBegin() + activeRelativeFrame);
|
||||
m_range = drop;
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::dropCels(DropOp op, const Range& drop)
|
||||
{
|
||||
ASSERT(drop.layerBegin() >= 0 && drop.layerBegin() < (int)m_layers.size());
|
||||
ASSERT(drop.layerEnd() >= 0 && drop.layerEnd() < (int)m_layers.size());
|
||||
ASSERT(drop.frameBegin() >= FrameNumber(0) && drop.frameBegin() < m_sprite->getTotalFrames());
|
||||
ASSERT(drop.frameEnd() >= FrameNumber(0) && drop.frameEnd() < m_sprite->getTotalFrames());
|
||||
|
||||
int srcLayerBegin, srcLayerStep, srcLayerEnd;
|
||||
int dstLayerBegin, dstLayerStep;
|
||||
FrameNumber srcFrameBegin, srcFrameStep, srcFrameEnd;
|
||||
FrameNumber dstFrameBegin, dstFrameStep;
|
||||
|
||||
if (drop.layerBegin() <= m_range.layerBegin()) {
|
||||
srcLayerBegin = m_range.layerBegin();
|
||||
srcLayerStep = 1;
|
||||
srcLayerEnd = m_range.layerEnd()+1;
|
||||
dstLayerBegin = drop.layerBegin();
|
||||
dstLayerStep = 1;
|
||||
}
|
||||
else {
|
||||
srcLayerBegin = m_range.layerEnd();
|
||||
srcLayerStep = -1;
|
||||
srcLayerEnd = m_range.layerBegin()-1;
|
||||
dstLayerBegin = drop.layerEnd();
|
||||
dstLayerStep = -1;
|
||||
}
|
||||
|
||||
if (drop.frameBegin() <= m_range.frameBegin()) {
|
||||
srcFrameBegin = m_range.frameBegin();
|
||||
srcFrameStep = FrameNumber(1);
|
||||
srcFrameEnd = m_range.frameEnd().next();
|
||||
dstFrameBegin = drop.frameBegin();
|
||||
dstFrameStep = FrameNumber(1);
|
||||
}
|
||||
else {
|
||||
srcFrameBegin = m_range.frameEnd();
|
||||
srcFrameStep = FrameNumber(-1);
|
||||
srcFrameEnd = m_range.frameBegin().previous();
|
||||
dstFrameBegin = drop.frameEnd();
|
||||
dstFrameStep = FrameNumber(-1);
|
||||
}
|
||||
|
||||
DocumentApi& api = m_document->getApi();
|
||||
|
||||
for (int srcLayerIdx = srcLayerBegin,
|
||||
dstLayerIdx = dstLayerBegin; srcLayerIdx != srcLayerEnd; ) {
|
||||
for (FrameNumber srcFrame = srcFrameBegin,
|
||||
dstFrame = dstFrameBegin; srcFrame != srcFrameEnd; ) {
|
||||
LayerImage* srcLayer = static_cast<LayerImage*>(m_layers[srcLayerIdx]);
|
||||
LayerImage* dstLayer = static_cast<LayerImage*>(m_layers[dstLayerIdx]);
|
||||
color_t bgcolor = app_get_color_to_clear_layer(dstLayer);
|
||||
|
||||
switch (op) {
|
||||
case Timeline::kMove: api.moveCel(m_sprite, srcLayer, dstLayer, srcFrame, dstFrame, bgcolor); break;
|
||||
case Timeline::kCopy: api.copyCel(m_sprite, srcLayer, dstLayer, srcFrame, dstFrame, bgcolor); break;
|
||||
}
|
||||
|
||||
srcFrame += srcFrameStep;
|
||||
dstFrame += dstFrameStep;
|
||||
}
|
||||
srcLayerIdx += srcLayerStep;
|
||||
dstLayerIdx += dstLayerStep;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::dropFrames(DropOp op, const Range& drop)
|
||||
{
|
||||
FrameNumber srcFrameBegin, srcFrameStep, srcFrameEnd;
|
||||
FrameNumber dstFrameBegin, dstFrameStep;
|
||||
|
||||
// TODO Try to add the range with just one call to DocumentApi
|
||||
// methods, to avoid generating a lot of SetCelFrame undoers (see
|
||||
// DocumentApi::setCelFramePosition).
|
||||
|
||||
switch (op) {
|
||||
|
||||
case Timeline::kMove:
|
||||
if (drop.frameBegin() <= m_range.frameBegin()) {
|
||||
srcFrameBegin = m_range.frameBegin();
|
||||
srcFrameStep = FrameNumber(1);
|
||||
srcFrameEnd = m_range.frameEnd().next();
|
||||
dstFrameBegin = drop.frameBegin();
|
||||
dstFrameStep = FrameNumber(1);
|
||||
}
|
||||
else {
|
||||
srcFrameBegin = m_range.frameEnd();
|
||||
srcFrameStep = FrameNumber(-1);
|
||||
srcFrameEnd = m_range.frameBegin().previous();
|
||||
dstFrameBegin = drop.frameEnd();
|
||||
dstFrameStep = FrameNumber(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case Timeline::kCopy:
|
||||
if (drop.frameBegin() <= m_range.frameBegin()) {
|
||||
srcFrameBegin = m_range.frameBegin();
|
||||
srcFrameStep = FrameNumber(2);
|
||||
srcFrameEnd = m_range.frameBegin().next(2*m_range.frames());
|
||||
dstFrameBegin = drop.frameBegin();
|
||||
dstFrameStep = FrameNumber(1);
|
||||
}
|
||||
else {
|
||||
srcFrameBegin = m_range.frameEnd();
|
||||
srcFrameStep = FrameNumber(-1);
|
||||
srcFrameEnd = m_range.frameBegin().previous();
|
||||
dstFrameBegin = drop.frameBegin();
|
||||
dstFrameStep = FrameNumber(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DocumentApi api = m_document->getApi();
|
||||
|
||||
for (FrameNumber srcFrame = srcFrameBegin,
|
||||
dstFrame = dstFrameBegin; srcFrame != srcFrameEnd; ) {
|
||||
switch (op) {
|
||||
case Timeline::kMove: api.moveFrame(m_sprite, srcFrame, dstFrame); break;
|
||||
case Timeline::kCopy: api.copyFrame(m_sprite, srcFrame, dstFrame); break;
|
||||
}
|
||||
|
||||
srcFrame += srcFrameStep;
|
||||
dstFrame += dstFrameStep;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::dropLayers(DropOp op, const Range& drop)
|
||||
{
|
||||
if (m_layers[m_clk_layer]->isBackground()) {
|
||||
Alert::show(PACKAGE "<<You can't move the `Background' layer.||&OK");
|
||||
return;
|
||||
}
|
||||
|
||||
Layer* firstLayer = m_layers[m_range.layerBegin()];
|
||||
Layer* lastLayer = m_layers[m_range.layerEnd()];
|
||||
std::vector<Layer*> layers = m_layers;
|
||||
|
||||
switch (op) {
|
||||
|
||||
case Timeline::kMove:
|
||||
for (int i = m_range.layerBegin(); i <= m_range.layerEnd(); ++i) {
|
||||
m_document->getApi().restackLayerAfter(
|
||||
layers[i], layers[drop.layerBegin()]);
|
||||
}
|
||||
break;
|
||||
|
||||
case Timeline::kCopy:
|
||||
for (int i = m_range.layerBegin(); i <= m_range.layerEnd(); ++i) {
|
||||
m_document->getApi().duplicateLayer(
|
||||
layers[i], layers[drop.layerBegin()]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Timeline::Range Timeline::getDropRange() const
|
||||
{
|
||||
Range drop;
|
||||
if (m_state != STATE_MOVING_RANGE)
|
||||
return drop;
|
||||
|
||||
switch (m_range.type()) {
|
||||
|
||||
case Range::kCels: {
|
||||
FrameNumber dx = m_hot_frame - m_clk_frame;
|
||||
int dy = m_hot_layer - m_clk_layer;
|
||||
int layerIdx;
|
||||
FrameNumber frame;
|
||||
|
||||
layerIdx = dy+m_range.layerBegin();
|
||||
layerIdx = MID(0, layerIdx, (int)m_layers.size() - m_range.layers());
|
||||
frame = dx+m_range.frameBegin();
|
||||
frame = MID(FrameNumber(0), frame, m_sprite->getTotalFrames() - m_range.frames());
|
||||
|
||||
drop.startRange(layerIdx, frame, m_range.type());
|
||||
drop.endRange(
|
||||
layerIdx+m_range.layers()-1,
|
||||
(frame+m_range.frames()).previous());
|
||||
break;
|
||||
}
|
||||
|
||||
case Range::kFrames: {
|
||||
FrameNumber frame = m_hot_frame;
|
||||
if (frame > m_range.frameBegin() && frame <= m_range.frameEnd())
|
||||
frame = m_range.frameBegin();
|
||||
|
||||
int layerIdx = getLayerIndex(m_layer);
|
||||
drop.startRange(layerIdx, frame, m_range.type());
|
||||
drop.endRange(layerIdx, frame);
|
||||
break;
|
||||
}
|
||||
|
||||
case Range::kLayers: {
|
||||
int layer = m_hot_layer;
|
||||
if (layer > m_range.layerBegin() && layer <= m_range.layerEnd())
|
||||
layer = m_range.layerBegin();
|
||||
|
||||
drop.startRange(layer, m_frame, m_range.type());
|
||||
drop.endRange(layer, m_frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return drop;
|
||||
}
|
||||
|
||||
void Timeline::Range::startRange(int layer, FrameNumber frame, Type type)
|
||||
{
|
||||
m_type = type;
|
||||
@ -1715,7 +1911,7 @@ void Timeline::Range::endRange(int layer, FrameNumber frame)
|
||||
|
||||
void Timeline::Range::disableRange()
|
||||
{
|
||||
m_type = None;
|
||||
m_type = kNone;
|
||||
}
|
||||
|
||||
bool Timeline::Range::inRange(int layer) const
|
||||
@ -1739,4 +1935,24 @@ bool Timeline::Range::inRange(int layer, FrameNumber frame) const
|
||||
return inRange(layer) && inRange(frame);
|
||||
}
|
||||
|
||||
void Timeline::Range::setLayers(int layers)
|
||||
{
|
||||
if (m_layerBegin <= m_layerEnd) m_layerEnd = m_layerBegin + layers - 1;
|
||||
else m_layerBegin = m_layerEnd + layers - 1;
|
||||
}
|
||||
|
||||
void Timeline::Range::setFrames(FrameNumber frames)
|
||||
{
|
||||
if (m_frameBegin <= m_frameEnd) m_frameEnd = (m_frameBegin + frames).previous();
|
||||
else m_frameBegin = (m_frameEnd + frames).previous();
|
||||
}
|
||||
|
||||
void Timeline::Range::displace(int layerDelta, FrameNumber frameDelta)
|
||||
{
|
||||
m_layerBegin += layerDelta;
|
||||
m_layerEnd += layerDelta;
|
||||
m_frameBegin += frameDelta;
|
||||
m_frameEnd += frameDelta;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -33,6 +33,7 @@
|
||||
namespace raster {
|
||||
class Cel;
|
||||
class Layer;
|
||||
class LayerImage;
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
@ -59,25 +60,29 @@ namespace app {
|
||||
STATE_SELECTING_FRAMES,
|
||||
STATE_SELECTING_CELS,
|
||||
STATE_MOVING_SEPARATOR,
|
||||
STATE_MOVING_LAYER,
|
||||
STATE_MOVING_CEL,
|
||||
STATE_MOVING_FRAME,
|
||||
STATE_MOVING_RANGE,
|
||||
STATE_MOVING_ONIONSKIN_RANGE_LEFT,
|
||||
STATE_MOVING_ONIONSKIN_RANGE_RIGHT
|
||||
};
|
||||
|
||||
struct Range {
|
||||
enum Type { None, Cels, Frames, Layers };
|
||||
enum Type { kNone, kCels, kFrames, kLayers };
|
||||
|
||||
Range() : m_type(None) { }
|
||||
Range() : m_type(kNone) { }
|
||||
|
||||
Type type() const { return m_type; }
|
||||
bool enabled() const { return m_type != None; }
|
||||
bool enabled() const { return m_type != kNone; }
|
||||
int layerBegin() const { return MIN(m_layerBegin, m_layerEnd); }
|
||||
int layerEnd() const { return MAX(m_layerBegin, m_layerEnd); }
|
||||
FrameNumber frameBegin() const { return MIN(m_frameBegin, m_frameEnd); }
|
||||
FrameNumber frameEnd() const { return MAX(m_frameBegin, m_frameEnd); }
|
||||
|
||||
int layers() const { return layerEnd() - layerBegin() + 1; }
|
||||
FrameNumber frames() const { return (frameEnd() - frameBegin()).next(); }
|
||||
void setLayers(int layers);
|
||||
void setFrames(FrameNumber frames);
|
||||
void displace(int layerDelta, FrameNumber frameDelta);
|
||||
|
||||
bool inRange(int layer) const;
|
||||
bool inRange(FrameNumber frame) const;
|
||||
bool inRange(int layer, FrameNumber frame) const;
|
||||
@ -86,6 +91,12 @@ namespace app {
|
||||
void endRange(int layer, FrameNumber frame);
|
||||
void disableRange();
|
||||
|
||||
bool operator==(const Range& o) const {
|
||||
return m_type == o.m_type &&
|
||||
layerBegin() == o.layerBegin() && layerEnd() == o.layerEnd() &&
|
||||
frameBegin() == o.frameBegin() && frameEnd() == o.frameEnd();
|
||||
}
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
int m_layerBegin;
|
||||
@ -94,6 +105,8 @@ namespace app {
|
||||
FrameNumber m_frameEnd;
|
||||
};
|
||||
|
||||
enum DropOp { kMove, kCopy };
|
||||
|
||||
Timeline();
|
||||
~Timeline();
|
||||
|
||||
@ -111,6 +124,10 @@ namespace app {
|
||||
|
||||
Range range() const { return m_range; }
|
||||
|
||||
// Drag-and-drop operations. These actions are used by commands
|
||||
// called from popup menus.
|
||||
void dropRange(DropOp op);
|
||||
|
||||
protected:
|
||||
bool onProcessMessage(ui::Message* msg) OVERRIDE;
|
||||
void onPreferredSize(ui::PreferredSizeEvent& ev) OVERRIDE;
|
||||
@ -165,6 +182,11 @@ namespace app {
|
||||
bool isLayerActive(int layer_index) const;
|
||||
bool isFrameActive(FrameNumber frame) const;
|
||||
void updateStatusBar();
|
||||
Range getDropRange() const;
|
||||
|
||||
void dropCels(DropOp op, const Range& drop);
|
||||
void dropFrames(DropOp op, const Range& drop);
|
||||
void dropLayers(DropOp op, const Range& drop);
|
||||
|
||||
skin::Style* m_timelineStyle;
|
||||
skin::Style* m_timelineBoxStyle;
|
||||
@ -187,6 +209,8 @@ namespace app {
|
||||
skin::Style* m_timelinePaddingBrStyle;
|
||||
skin::Style* m_timelineSelectedCelStyle;
|
||||
skin::Style* m_timelineRangeOutlineStyle;
|
||||
skin::Style* m_timelineDropLayerDecoStyle;
|
||||
skin::Style* m_timelineDropFrameDecoStyle;
|
||||
Context* m_context;
|
||||
Editor* m_editor;
|
||||
Document* m_document;
|
||||
@ -209,7 +233,7 @@ namespace app {
|
||||
int m_clk_part;
|
||||
int m_clk_layer;
|
||||
FrameNumber m_clk_frame;
|
||||
// Old mouse position (for scrolling).
|
||||
// Absolute mouse positions for scrolling.
|
||||
gfx::Point m_oldPos;
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "app/undoers/set_cel_frame.h"
|
||||
|
||||
#include "raster/cel.h"
|
||||
#include "raster/layer.h"
|
||||
#include "undo/objects_container.h"
|
||||
#include "undo/undoers_collector.h"
|
||||
|
||||
@ -31,8 +32,9 @@ namespace undoers {
|
||||
|
||||
using namespace undo;
|
||||
|
||||
SetCelFrame::SetCelFrame(ObjectsContainer* objects, Cel* cel)
|
||||
: m_celId(objects->addObject(cel))
|
||||
SetCelFrame::SetCelFrame(ObjectsContainer* objects, LayerImage* layer, Cel* cel)
|
||||
: m_layerId(objects->addObject(layer))
|
||||
, m_celId(objects->addObject(cel))
|
||||
, m_frame(cel->getFrame())
|
||||
{
|
||||
}
|
||||
@ -44,12 +46,13 @@ void SetCelFrame::dispose()
|
||||
|
||||
void SetCelFrame::revert(ObjectsContainer* objects, UndoersCollector* redoers)
|
||||
{
|
||||
LayerImage* layer = objects->getObjectT<LayerImage>(m_layerId);
|
||||
Cel* cel = objects->getObjectT<Cel>(m_celId);
|
||||
|
||||
// Push another SetCelFrame as redoer
|
||||
redoers->pushUndoer(new SetCelFrame(objects, cel));
|
||||
redoers->pushUndoer(new SetCelFrame(objects, layer, cel));
|
||||
|
||||
cel->setFrame(m_frame);
|
||||
layer->moveCel(cel, m_frame);
|
||||
}
|
||||
|
||||
} // namespace undoers
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
namespace raster {
|
||||
class Cel;
|
||||
class Layer;
|
||||
class LayerImage;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
@ -36,13 +36,14 @@ namespace app {
|
||||
|
||||
class SetCelFrame : public UndoerBase {
|
||||
public:
|
||||
SetCelFrame(ObjectsContainer* objects, Cel* cel);
|
||||
SetCelFrame(ObjectsContainer* objects, LayerImage* layer, Cel* cel);
|
||||
|
||||
void dispose() OVERRIDE;
|
||||
size_t getMemSize() const OVERRIDE { return sizeof(*this); }
|
||||
void revert(ObjectsContainer* objects, UndoersCollector* redoers) OVERRIDE;
|
||||
|
||||
private:
|
||||
ObjectId m_layerId;
|
||||
ObjectId m_celId;
|
||||
FrameNumber m_frame;
|
||||
};
|
||||
|
@ -1,268 +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/util/celmove.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/color.h"
|
||||
#include "app/console.h"
|
||||
#include "app/context_access.h"
|
||||
#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_cel.h"
|
||||
#include "app/undoers/remove_image.h"
|
||||
#include "app/undoers/replace_image.h"
|
||||
#include "app/undoers/set_cel_frame.h"
|
||||
#include "app/undoers/set_cel_opacity.h"
|
||||
#include "app/undoers/set_cel_position.h"
|
||||
#include "raster/blend.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
// These variables indicate what cel to move (and the sprite's frame
|
||||
// indicates where to move it).
|
||||
static Layer* src_layer = NULL; // TODO warning not thread safe
|
||||
static Layer* dst_layer = NULL;
|
||||
static FrameNumber src_frame = FrameNumber(0);
|
||||
static FrameNumber dst_frame = FrameNumber(0);
|
||||
|
||||
static void remove_cel(Sprite* sprite, UndoTransaction& undo, LayerImage* layer, Cel* cel);
|
||||
|
||||
void set_frame_to_handle(Layer* _src_layer, FrameNumber _src_frame,
|
||||
Layer* _dst_layer, FrameNumber _dst_frame)
|
||||
{
|
||||
src_layer = _src_layer;
|
||||
src_frame = _src_frame;
|
||||
dst_layer = _dst_layer;
|
||||
dst_frame = _dst_frame;
|
||||
}
|
||||
|
||||
void move_cel(ContextWriter& writer)
|
||||
{
|
||||
Document* document = writer.document();
|
||||
Sprite* sprite = writer.sprite();
|
||||
Cel *src_cel, *dst_cel;
|
||||
|
||||
ASSERT(src_layer != NULL);
|
||||
ASSERT(dst_layer != NULL);
|
||||
ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames());
|
||||
ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames());
|
||||
|
||||
if (src_layer->isBackground()) {
|
||||
copy_cel(writer);
|
||||
return;
|
||||
}
|
||||
|
||||
src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame);
|
||||
dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame);
|
||||
|
||||
UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument);
|
||||
|
||||
/* remove the 'dst_cel' (if it exists) because it must be
|
||||
replaced with 'src_cel' */
|
||||
if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL))
|
||||
remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel);
|
||||
|
||||
/* move the cel in the same layer */
|
||||
if (src_cel != NULL) {
|
||||
if (src_layer == dst_layer) {
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::SetCelFrame(undo.getObjects(), src_cel));
|
||||
|
||||
src_cel->setFrame(dst_frame);
|
||||
}
|
||||
/* move the cel in different layers */
|
||||
else {
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), src_layer, src_cel));
|
||||
static_cast<LayerImage*>(src_layer)->removeCel(src_cel);
|
||||
|
||||
src_cel->setFrame(dst_frame);
|
||||
|
||||
/* if we are moving a cel from a transparent layer to the
|
||||
background layer, we have to clear the background of the
|
||||
image */
|
||||
if (!src_layer->isBackground() &&
|
||||
dst_layer->isBackground()) {
|
||||
Image* src_image = sprite->getStock()->getImage(src_cel->getImage());
|
||||
Image* dst_image = crop_image(src_image,
|
||||
-src_cel->getX(),
|
||||
-src_cel->getY(),
|
||||
sprite->getWidth(),
|
||||
sprite->getHeight(), 0);
|
||||
|
||||
if (undo.isEnabled()) {
|
||||
undo.pushUndoer(new undoers::ReplaceImage(undo.getObjects(),
|
||||
sprite->getStock(), src_cel->getImage()));
|
||||
undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), src_cel));
|
||||
undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), src_cel));
|
||||
}
|
||||
|
||||
clear_image(dst_image, app_get_color_to_clear_layer(dst_layer));
|
||||
composite_image(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
|
||||
src_cel->setPosition(0, 0);
|
||||
src_cel->setOpacity(255);
|
||||
|
||||
sprite->getStock()->replaceImage(src_cel->getImage(), dst_image);
|
||||
delete src_image;
|
||||
}
|
||||
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, src_cel));
|
||||
|
||||
static_cast<LayerImage*>(dst_layer)->addCel(src_cel);
|
||||
}
|
||||
}
|
||||
|
||||
undo.commit();
|
||||
|
||||
document->notifyCelMoved(src_layer, src_frame, dst_layer, dst_frame);
|
||||
set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0));
|
||||
}
|
||||
|
||||
void copy_cel(ContextWriter& writer)
|
||||
{
|
||||
Document* document = writer.document();
|
||||
Sprite* sprite = writer.sprite();
|
||||
UndoTransaction undo(writer.context(), "Move Cel", undo::ModifyDocument);
|
||||
Cel *src_cel, *dst_cel;
|
||||
|
||||
ASSERT(src_layer != NULL);
|
||||
ASSERT(dst_layer != NULL);
|
||||
ASSERT(src_frame >= 0 && src_frame < sprite->getTotalFrames());
|
||||
ASSERT(dst_frame >= 0 && dst_frame < sprite->getTotalFrames());
|
||||
|
||||
src_cel = static_cast<LayerImage*>(src_layer)->getCel(src_frame);
|
||||
dst_cel = static_cast<LayerImage*>(dst_layer)->getCel(dst_frame);
|
||||
|
||||
// Remove the 'dst_cel' (if it exists) because it must be replaced
|
||||
// with 'src_cel'
|
||||
if ((dst_cel != NULL) && (!dst_layer->isBackground() || src_cel != NULL))
|
||||
remove_cel(sprite, undo, static_cast<LayerImage*>(dst_layer), dst_cel);
|
||||
|
||||
// Move the cel in the same layer.
|
||||
if (src_cel != NULL) {
|
||||
Image *src_image = sprite->getStock()->getImage(src_cel->getImage());
|
||||
Image *dst_image;
|
||||
int image_index;
|
||||
int dst_cel_x;
|
||||
int dst_cel_y;
|
||||
int dst_cel_opacity;
|
||||
|
||||
// If we are moving a cel from a transparent layer to the
|
||||
// background layer, we have to clear the background of the image.
|
||||
if (!src_layer->isBackground() &&
|
||||
dst_layer->isBackground()) {
|
||||
dst_image = crop_image(src_image,
|
||||
-src_cel->getX(),
|
||||
-src_cel->getY(),
|
||||
sprite->getWidth(),
|
||||
sprite->getHeight(), 0);
|
||||
|
||||
clear_image(dst_image, app_get_color_to_clear_layer(dst_layer));
|
||||
composite_image(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
|
||||
dst_cel_x = 0;
|
||||
dst_cel_y = 0;
|
||||
dst_cel_opacity = 255;
|
||||
}
|
||||
else {
|
||||
dst_image = Image::createCopy(src_image);
|
||||
dst_cel_x = src_cel->getX();
|
||||
dst_cel_y = src_cel->getY();
|
||||
dst_cel_opacity = src_cel->getOpacity();
|
||||
}
|
||||
|
||||
// Add the image in the stock
|
||||
image_index = sprite->getStock()->addImage(dst_image);
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::AddImage(undo.getObjects(),
|
||||
sprite->getStock(), image_index));
|
||||
|
||||
// Create the new cel
|
||||
dst_cel = new Cel(dst_frame, image_index);
|
||||
dst_cel->setPosition(dst_cel_x, dst_cel_y);
|
||||
dst_cel->setOpacity(dst_cel_opacity);
|
||||
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::AddCel(undo.getObjects(), dst_layer, dst_cel));
|
||||
|
||||
static_cast<LayerImage*>(dst_layer)->addCel(dst_cel);
|
||||
}
|
||||
|
||||
undo.commit();
|
||||
|
||||
document->notifyCelCopied(src_layer, src_frame, dst_layer, dst_frame);
|
||||
set_frame_to_handle(NULL, FrameNumber(0), NULL, FrameNumber(0));
|
||||
}
|
||||
|
||||
static void remove_cel(Sprite* sprite, UndoTransaction& undo, LayerImage *layer, Cel *cel)
|
||||
{
|
||||
Image *image;
|
||||
Cel *it;
|
||||
bool used;
|
||||
|
||||
if (sprite != NULL && layer->isImage() && cel != NULL) {
|
||||
/* find if the image that use the cel to remove, is used by
|
||||
another cels */
|
||||
used = false;
|
||||
for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
|
||||
it = layer->getCel(frame);
|
||||
if (it != NULL && it != cel && it->getImage() == cel->getImage()) {
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!used) {
|
||||
// If the image is only used by this cel, we can remove the
|
||||
// image from the stock.
|
||||
image = sprite->getStock()->getImage(cel->getImage());
|
||||
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::RemoveImage(undo.getObjects(),
|
||||
sprite->getStock(), cel->getImage()));
|
||||
|
||||
sprite->getStock()->removeImage(image);
|
||||
delete image;
|
||||
}
|
||||
|
||||
if (undo.isEnabled()) {
|
||||
undo.pushUndoer(new undoers::RemoveCel(undo.getObjects(), layer, cel));
|
||||
}
|
||||
|
||||
// Remove the cel
|
||||
layer->removeCel(cel);
|
||||
delete cel;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -1,43 +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_UTIL_CELMOVE_H_INCLUDED
|
||||
#define APP_UTIL_CELMOVE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "raster/frame_number.h"
|
||||
|
||||
namespace raster {
|
||||
class Cel;
|
||||
class Layer;
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class ContextWriter;
|
||||
using namespace raster;
|
||||
|
||||
void set_frame_to_handle(Layer* src_layer, FrameNumber src_frame,
|
||||
Layer* dst_layer, FrameNumber dst_frame);
|
||||
|
||||
void move_cel(ContextWriter& writer);
|
||||
void copy_cel(ContextWriter& writer);
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -39,6 +39,9 @@ namespace raster {
|
||||
int getY() const { return m_y; }
|
||||
int getOpacity() const { return m_opacity; }
|
||||
|
||||
// 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(FrameNumber frame) { m_frame = frame; }
|
||||
void setImage(int image) { m_image = image; }
|
||||
void setPosition(int x, int y) { m_x = x; m_y = y; }
|
||||
|
@ -38,6 +38,8 @@ namespace raster {
|
||||
FrameNumber& operator--() { --m_value; return *this; }
|
||||
FrameNumber operator++(int) { FrameNumber old(*this); ++m_value; return old; }
|
||||
FrameNumber operator--(int) { FrameNumber old(*this); --m_value; return old; }
|
||||
FrameNumber& operator+=(const FrameNumber& o) { m_value += o.m_value; return *this; }
|
||||
FrameNumber& operator-=(const FrameNumber& o) { m_value -= o.m_value; return *this; }
|
||||
bool operator<(const FrameNumber& o) const { return m_value < o.m_value; }
|
||||
bool operator>(const FrameNumber& o) const { return m_value > o.m_value; }
|
||||
bool operator<=(const FrameNumber& o) const { return m_value <= o.m_value; }
|
||||
|
@ -174,6 +174,13 @@ void LayerImage::removeCel(Cel *cel)
|
||||
m_cels.erase(it);
|
||||
}
|
||||
|
||||
void LayerImage::moveCel(Cel* cel, FrameNumber frame)
|
||||
{
|
||||
removeCel(cel);
|
||||
cel->setFrame(frame);
|
||||
addCel(cel);
|
||||
}
|
||||
|
||||
const Cel* LayerImage::getCel(FrameNumber frame) const
|
||||
{
|
||||
CelConstIterator it = getCelBegin();
|
||||
|
@ -107,6 +107,7 @@ namespace raster {
|
||||
|
||||
void addCel(Cel *cel);
|
||||
void removeCel(Cel *cel);
|
||||
void moveCel(Cel *cel, FrameNumber frame);
|
||||
const Cel* getCel(FrameNumber frame) const;
|
||||
Cel* getCel(FrameNumber frame);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user