mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-10 01:13:49 +00:00
Restore selected Timeline range after undo/redo
This commit is contained in:
parent
db097d3e67
commit
b8445956ae
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -13,19 +13,61 @@
|
||||
#include "app/context.h"
|
||||
#include "doc/site.h"
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
#include "app/app.h"
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#endif
|
||||
|
||||
namespace app {
|
||||
|
||||
CmdTransaction::CmdTransaction(const std::string& label,
|
||||
bool changeSavedState, int* savedCounter)
|
||||
: m_label(label)
|
||||
bool changeSavedState,
|
||||
int* savedCounter)
|
||||
: m_ranges(nullptr)
|
||||
, m_label(label)
|
||||
, m_changeSavedState(changeSavedState)
|
||||
, m_savedCounter(savedCounter)
|
||||
{
|
||||
}
|
||||
|
||||
void CmdTransaction::setNewDocumentRange(const DocumentRange& range)
|
||||
{
|
||||
#ifdef ENABLE_UI
|
||||
if (m_ranges)
|
||||
range.write(m_ranges->m_after);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CmdTransaction::commit()
|
||||
{
|
||||
m_spritePositionAfter = calcSpritePosition();
|
||||
|
||||
// We cannot capture m_ranges->m_after from the Timeline here
|
||||
// because the document range in the Timeline is updated after the
|
||||
// commit/command (on Timeline::onAfterCommandExecution).
|
||||
//
|
||||
// So m_ranges->m_after is captured explicitly in
|
||||
// setNewDocumentRange().
|
||||
}
|
||||
|
||||
std::istream* CmdTransaction::documentRangeBeforeExecute() const
|
||||
{
|
||||
if (m_ranges && m_ranges->m_before.tellp() > 0) {
|
||||
m_ranges->m_before.seekg(0);
|
||||
return &m_ranges->m_before;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::istream* CmdTransaction::documentRangeAfterExecute() const
|
||||
{
|
||||
if (m_ranges && m_ranges->m_after.tellp() > 0) {
|
||||
m_ranges->m_after.seekg(0);
|
||||
return &m_ranges->m_after;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CmdTransaction::onExecute()
|
||||
@ -35,6 +77,12 @@ void CmdTransaction::onExecute()
|
||||
// The execution of CmdTransaction is called by Transaction at the
|
||||
// very beginning, just to save the current sprite position.
|
||||
m_spritePositionBefore = calcSpritePosition();
|
||||
#ifdef ENABLE_UI
|
||||
if (isDocumentRangeEnabled()) {
|
||||
m_ranges.reset(new Ranges);
|
||||
calcDocumentRange().write(m_ranges->m_before);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_changeSavedState)
|
||||
++(*m_savedCounter);
|
||||
@ -61,10 +109,47 @@ std::string CmdTransaction::onLabel() const
|
||||
return m_label;
|
||||
}
|
||||
|
||||
doc::SpritePosition CmdTransaction::calcSpritePosition()
|
||||
size_t CmdTransaction::onMemSize() const
|
||||
{
|
||||
size_t size = CmdSequence::onMemSize();
|
||||
if (m_ranges) {
|
||||
size += (m_ranges->m_before.tellp() +
|
||||
m_ranges->m_after.tellp());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
doc::SpritePosition CmdTransaction::calcSpritePosition() const
|
||||
{
|
||||
doc::Site site = context()->activeSite();
|
||||
return doc::SpritePosition(site.layer(), site.frame());
|
||||
}
|
||||
|
||||
bool CmdTransaction::isDocumentRangeEnabled() const
|
||||
{
|
||||
#ifdef ENABLE_UI
|
||||
if (App::instance()) {
|
||||
Timeline* timeline = App::instance()->timeline();
|
||||
if (timeline && timeline->range().enabled())
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
DocumentRange CmdTransaction::calcDocumentRange() const
|
||||
{
|
||||
#ifdef ENABLE_UI
|
||||
// TODO We cannot use Context::activeSite() because it losts
|
||||
// important information about the DocumentRange() (type and
|
||||
// flags).
|
||||
if (App::instance()) {
|
||||
Timeline* timeline = App::instance()->timeline();
|
||||
if (timeline)
|
||||
return timeline->range();
|
||||
}
|
||||
#endif
|
||||
return DocumentRange();
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -9,6 +9,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "app/cmd_sequence.h"
|
||||
#include "app/document_range.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -19,22 +23,35 @@ namespace app {
|
||||
CmdTransaction(const std::string& label,
|
||||
bool changeSavedState, int* savedCounter);
|
||||
|
||||
void setNewDocumentRange(const DocumentRange& range);
|
||||
void commit();
|
||||
|
||||
doc::SpritePosition spritePositionBeforeExecute() const { return m_spritePositionBefore; }
|
||||
doc::SpritePosition spritePositionAfterExecute() const { return m_spritePositionAfter; }
|
||||
|
||||
std::istream* documentRangeBeforeExecute() const;
|
||||
std::istream* documentRangeAfterExecute() const;
|
||||
|
||||
protected:
|
||||
void onExecute() override;
|
||||
void onUndo() override;
|
||||
void onRedo() override;
|
||||
std::string onLabel() const override;
|
||||
size_t onMemSize() const override;
|
||||
|
||||
private:
|
||||
doc::SpritePosition calcSpritePosition();
|
||||
doc::SpritePosition calcSpritePosition() const;
|
||||
bool isDocumentRangeEnabled() const;
|
||||
DocumentRange calcDocumentRange() const;
|
||||
|
||||
struct Ranges {
|
||||
std::stringstream m_before;
|
||||
std::stringstream m_after;
|
||||
};
|
||||
|
||||
doc::SpritePosition m_spritePositionBefore;
|
||||
doc::SpritePosition m_spritePositionAfter;
|
||||
std::unique_ptr<Ranges> m_ranges;
|
||||
std::string m_label;
|
||||
bool m_changeSavedState;
|
||||
int* m_savedCounter;
|
||||
|
@ -24,6 +24,10 @@
|
||||
#include "ui/manager.h"
|
||||
#include "ui/system.h"
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#endif
|
||||
|
||||
namespace app {
|
||||
|
||||
class UndoCommand : public Command {
|
||||
@ -93,13 +97,23 @@ void UndoCommand::onExecute(Context* context)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the stream to deserialize the document range after executing
|
||||
// the undo/redo action. We cannot yet deserialize the document
|
||||
// range because there could be inexistent layers.
|
||||
std::istream* docRangeStream;
|
||||
if (m_type == Undo)
|
||||
docRangeStream = undo->nextUndoDocumentRange();
|
||||
else
|
||||
docRangeStream = undo->nextRedoDocumentRange();
|
||||
|
||||
StatusBar* statusbar = StatusBar::instance();
|
||||
if (statusbar)
|
||||
if (statusbar) {
|
||||
statusbar->showTip(1000, "%s %s",
|
||||
(m_type == Undo ? "Undid": "Redid"),
|
||||
(m_type == Undo ?
|
||||
undo->nextUndoLabel().c_str():
|
||||
undo->nextRedoLabel().c_str()));
|
||||
}
|
||||
#endif // ENABLE_UI
|
||||
|
||||
// Effectively undo/redo.
|
||||
@ -124,6 +138,18 @@ void UndoCommand::onExecute(Context* context)
|
||||
current_editor->setFrame(spritePosition.frame());
|
||||
}
|
||||
}
|
||||
|
||||
// Update timeline range. We've to deserialize the DocumentRange at
|
||||
// this point when objects (possible layers) are re-created after
|
||||
// the undo and we can deserialize them.
|
||||
if (docRangeStream) {
|
||||
Timeline* timeline = App::instance()->timeline();
|
||||
if (timeline) {
|
||||
DocumentRange docRange;
|
||||
if (docRange.read(*docRangeStream))
|
||||
timeline->setRange(docRange);
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_UI
|
||||
|
||||
document->generateMaskBoundaries();
|
||||
|
@ -10,13 +10,18 @@
|
||||
|
||||
#include "app/document_range.h"
|
||||
|
||||
#include "base/serialization.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace base::serialization;
|
||||
using namespace base::serialization::little_endian;
|
||||
using namespace doc;
|
||||
|
||||
DocumentRange::DocumentRange()
|
||||
@ -154,6 +159,35 @@ bool DocumentRange::convertToCels(const Sprite* sprite)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DocumentRange::write(std::ostream& os) const
|
||||
{
|
||||
write32(os, m_type);
|
||||
write32(os, m_flags);
|
||||
|
||||
if (!m_selectedLayers.write(os)) return false;
|
||||
if (!m_selectedFrames.write(os)) return false;
|
||||
|
||||
write32(os, m_selectingFromLayer ? m_selectingFromLayer->id(): 0);
|
||||
write32(os, m_selectingFromFrame);
|
||||
return os.good();
|
||||
}
|
||||
|
||||
bool DocumentRange::read(std::istream& is)
|
||||
{
|
||||
clearRange();
|
||||
|
||||
m_type = (Type)read32(is);
|
||||
m_flags = read32(is);
|
||||
|
||||
if (!m_selectedLayers.read(is)) return false;
|
||||
if (!m_selectedFrames.read(is)) return false;
|
||||
|
||||
ObjectId id = read32(is);
|
||||
m_selectingFromLayer = doc::get<Layer>(id);
|
||||
m_selectingFromFrame = read32(is);
|
||||
return is.good();
|
||||
}
|
||||
|
||||
void DocumentRange::selectLayerRange(Layer* fromLayer, Layer* toLayer)
|
||||
{
|
||||
ASSERT(fromLayer);
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "doc/selected_frames.h"
|
||||
#include "doc/selected_layers.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace doc {
|
||||
class Cel;
|
||||
class Sprite;
|
||||
@ -64,6 +66,9 @@ namespace app {
|
||||
|
||||
bool convertToCels(const Sprite* sprite);
|
||||
|
||||
bool write(std::ostream& os) const;
|
||||
bool read(std::istream& is);
|
||||
|
||||
private:
|
||||
void selectLayerRange(Layer* fromLayer, Layer* toLayer);
|
||||
void selectFrameRange(frame_t fromFrame, frame_t toFrame);
|
||||
|
@ -13,10 +13,12 @@
|
||||
|
||||
#include "app/document_range_ops.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/document_api.h"
|
||||
#include "app/document_range.h"
|
||||
#include "app/transaction.h"
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
@ -30,13 +32,12 @@ namespace app {
|
||||
|
||||
enum Op { Move, Copy };
|
||||
|
||||
template<typename T>
|
||||
static void move_or_copy_cels(
|
||||
DocumentApi& api, Op op,
|
||||
LayerList& srcLayers,
|
||||
LayerList& dstLayers,
|
||||
T& srcFrames,
|
||||
T& dstFrames)
|
||||
const LayerList& srcLayers,
|
||||
const LayerList& dstLayers,
|
||||
const SelectedFrames& srcFrames,
|
||||
const SelectedFrames& dstFrames)
|
||||
{
|
||||
ASSERT(srcLayers.size() == dstLayers.size());
|
||||
|
||||
@ -74,13 +75,14 @@ static void move_or_copy_cels(
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static DocumentRange move_or_copy_frames(
|
||||
DocumentApi& api, Op op,
|
||||
Sprite* sprite,
|
||||
T& srcFrames,
|
||||
const DocumentRange& srcRange,
|
||||
frame_t dstFrame)
|
||||
{
|
||||
const SelectedFrames& srcFrames = srcRange.selectedFrames();
|
||||
|
||||
#ifdef TRACE_RANGE_OPS
|
||||
std::clog << "move_or_copy_frames frames[";
|
||||
for (auto srcFrame : srcFrames) {
|
||||
@ -161,6 +163,8 @@ static DocumentRange move_or_copy_frames(
|
||||
}
|
||||
|
||||
DocumentRange result;
|
||||
if (!srcRange.selectedLayers().empty())
|
||||
result.selectLayers(srcRange.selectedLayers());
|
||||
result.startRange(nullptr, dstFrame-srcFrames.size(), DocumentRange::kFrames);
|
||||
result.endRange(nullptr, dstFrame-1);
|
||||
return result;
|
||||
@ -327,8 +331,8 @@ static DocumentRange drop_range_op(
|
||||
}
|
||||
|
||||
if (from.firstFrame() < to.firstFrame()) {
|
||||
auto srcFrames = from.selectedFrames().reversed();
|
||||
auto dstFrames = to.selectedFrames().reversed();
|
||||
auto srcFrames = from.selectedFrames().makeReverse();
|
||||
auto dstFrames = to.selectedFrames().makeReverse();
|
||||
|
||||
move_or_copy_cels(api, op, srcLayers, dstLayers, srcFrames, dstFrames);
|
||||
}
|
||||
@ -350,9 +354,7 @@ static DocumentRange drop_range_op(
|
||||
else
|
||||
dstFrame = to.lastFrame()+1;
|
||||
|
||||
resultRange =
|
||||
move_or_copy_frames(api, op, sprite,
|
||||
from.selectedFrames(), dstFrame);
|
||||
resultRange = move_or_copy_frames(api, op, sprite, from, dstFrame);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -423,6 +425,9 @@ static DocumentRange drop_range_op(
|
||||
}
|
||||
}
|
||||
|
||||
if (resultRange.type() != DocumentRange::kNone)
|
||||
transaction.setNewDocumentRange(resultRange);
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
@ -498,6 +503,7 @@ void reverse_frames(Document* doc, const DocumentRange& range)
|
||||
}
|
||||
}
|
||||
|
||||
transaction.setNewDocumentRange(range);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -187,6 +187,24 @@ SpritePosition DocumentUndo::nextRedoSpritePosition() const
|
||||
return SpritePosition();
|
||||
}
|
||||
|
||||
std::istream* DocumentUndo::nextUndoDocumentRange() const
|
||||
{
|
||||
const undo::UndoState* state = nextUndo();
|
||||
if (state)
|
||||
return STATE_CMD(state)->documentRangeBeforeExecute();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::istream* DocumentUndo::nextRedoDocumentRange() const
|
||||
{
|
||||
const undo::UndoState* state = nextRedo();
|
||||
if (state)
|
||||
return STATE_CMD(state)->documentRangeAfterExecute();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Cmd* DocumentUndo::lastExecutedCmd() const
|
||||
{
|
||||
const undo::UndoState* state = m_undoHistory.currentState();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -8,12 +8,14 @@
|
||||
#define APP_DOCUMENT_UNDO_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/document_range.h"
|
||||
#include "base/disable_copying.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "doc/sprite_position.h"
|
||||
#include "obs/observable.h"
|
||||
#include "undo/undo_history.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
namespace doc {
|
||||
@ -54,6 +56,8 @@ namespace app {
|
||||
|
||||
SpritePosition nextUndoSpritePosition() const;
|
||||
SpritePosition nextRedoSpritePosition() const;
|
||||
std::istream* nextUndoDocumentRange() const;
|
||||
std::istream* nextRedoDocumentRange() const;
|
||||
|
||||
Cmd* lastExecutedCmd() const;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -50,6 +50,15 @@ Transaction::~Transaction()
|
||||
}
|
||||
}
|
||||
|
||||
// Used to set the document range after all the transaction is
|
||||
// executed and before the commit. This range is stored in
|
||||
// CmdTransaction to recover it on Edit > Redo.
|
||||
void Transaction::setNewDocumentRange(const DocumentRange& range)
|
||||
{
|
||||
ASSERT(m_cmds);
|
||||
m_cmds->setNewDocumentRange(range);
|
||||
}
|
||||
|
||||
void Transaction::commit()
|
||||
{
|
||||
ASSERT(m_cmds);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -15,6 +15,7 @@ namespace app {
|
||||
class Cmd;
|
||||
class CmdTransaction;
|
||||
class Context;
|
||||
class DocumentRange;
|
||||
class DocumentUndo;
|
||||
|
||||
enum Modification {
|
||||
@ -45,6 +46,11 @@ namespace app {
|
||||
Transaction(Context* ctx, const std::string& label, Modification mod = ModifyDocument);
|
||||
virtual ~Transaction();
|
||||
|
||||
// Can be used to change the new document range resulting from
|
||||
// executing this transaction. This range can be used then in
|
||||
// undo/redo operations to restore the Timeline selection/range.
|
||||
void setNewDocumentRange(const DocumentRange& range);
|
||||
|
||||
// This must be called to commit all the changes, so the undo will
|
||||
// be finally added in the sprite.
|
||||
//
|
||||
|
@ -503,7 +503,7 @@ void Timeline::prepareToMoveRange()
|
||||
m_moveRangeData.activeRelativeFrame = j;
|
||||
}
|
||||
|
||||
void Timeline::moveRange(Range& range)
|
||||
void Timeline::moveRange(const Range& range)
|
||||
{
|
||||
regenerateRows();
|
||||
|
||||
@ -535,6 +535,12 @@ void Timeline::moveRange(Range& range)
|
||||
m_range = range;
|
||||
}
|
||||
|
||||
void Timeline::setRange(const Range& range)
|
||||
{
|
||||
m_range = range;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void Timeline::activateClipboardRange()
|
||||
{
|
||||
m_clipboard_timer.start();
|
||||
|
@ -93,7 +93,8 @@ namespace app {
|
||||
const SelectedFrames& selectedFrames() const { return m_range.selectedFrames(); }
|
||||
|
||||
void prepareToMoveRange();
|
||||
void moveRange(Range& range);
|
||||
void moveRange(const Range& range);
|
||||
void setRange(const Range& range);
|
||||
|
||||
void activateClipboardRange();
|
||||
|
||||
|
@ -12,11 +12,16 @@
|
||||
|
||||
#include "base/base.h"
|
||||
#include "base/debug.h"
|
||||
#include "base/serialization.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
namespace doc {
|
||||
|
||||
using namespace base::serialization;
|
||||
using namespace base::serialization::little_endian;
|
||||
|
||||
std::size_t SelectedFrames::size() const
|
||||
{
|
||||
std::size_t size = 0;
|
||||
@ -172,4 +177,25 @@ SelectedFrames SelectedFrames::makePingPong() const
|
||||
return newFrames;
|
||||
}
|
||||
|
||||
bool SelectedFrames::write(std::ostream& os) const
|
||||
{
|
||||
write32(os, size());
|
||||
for (const frame_t frame : *this) {
|
||||
write32(os, frame);
|
||||
}
|
||||
return os.good();
|
||||
}
|
||||
|
||||
bool SelectedFrames::read(std::istream& is)
|
||||
{
|
||||
clear();
|
||||
|
||||
int nframes = read32(is);
|
||||
for (int i=0; i<nframes && is; ++i) {
|
||||
frame_t frame = read32(is);
|
||||
insert(frame);
|
||||
}
|
||||
return is.good();
|
||||
}
|
||||
|
||||
} // namespace doc
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "doc/frame_range.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
@ -156,6 +157,9 @@ namespace doc {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
bool write(std::ostream& os) const;
|
||||
bool read(std::istream& is);
|
||||
|
||||
private:
|
||||
Ranges m_ranges;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2016 David Capello
|
||||
// Copyright (c) 2016, 2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -12,11 +12,17 @@
|
||||
|
||||
#include "base/base.h"
|
||||
#include "base/debug.h"
|
||||
#include "base/serialization.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace doc {
|
||||
|
||||
using namespace base::serialization;
|
||||
using namespace base::serialization::little_endian;
|
||||
|
||||
void SelectedLayers::clear()
|
||||
{
|
||||
m_set.clear();
|
||||
@ -184,4 +190,34 @@ void SelectedLayers::propagateSelection()
|
||||
insert(layer);
|
||||
}
|
||||
|
||||
bool SelectedLayers::write(std::ostream& os) const
|
||||
{
|
||||
write32(os, size());
|
||||
for (const Layer* layer : *this)
|
||||
write32(os, layer->id());
|
||||
return os.good();
|
||||
}
|
||||
|
||||
bool SelectedLayers::read(std::istream& is)
|
||||
{
|
||||
clear();
|
||||
|
||||
int nlayers = read32(is);
|
||||
for (int i=0; i<nlayers && is; ++i) {
|
||||
ObjectId id = read32(is);
|
||||
Layer* layer = doc::get<Layer>(id);
|
||||
|
||||
// Check that the layer does exist. You will see a little trick in
|
||||
// UndoCommand::onExecute() deserializing the DocumentRange stream
|
||||
// after the undo/redo is executed so layers exist at this point.
|
||||
|
||||
// TODO This should be an assert, but there is a bug that make this fail
|
||||
//ASSERT(layer);
|
||||
|
||||
if (layer)
|
||||
insert(layer);
|
||||
}
|
||||
return is.good();
|
||||
}
|
||||
|
||||
} // namespace doc
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2016-2017 David Capello
|
||||
// Copyright (c) 2016-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -8,9 +8,11 @@
|
||||
#define DOC_SELECTED_LAYERS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include "layer_list.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <set>
|
||||
|
||||
namespace doc {
|
||||
|
||||
class Layer;
|
||||
@ -52,6 +54,9 @@ namespace doc {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
bool write(std::ostream& os) const;
|
||||
bool read(std::istream& is);
|
||||
|
||||
private:
|
||||
Set m_set;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user