Skip to content

Commit

Permalink
UndoRedo: Implement keyframe addition
Browse files Browse the repository at this point in the history
  • Loading branch information
MrStevns committed Sep 28, 2024
1 parent 6d74898 commit cf4b62e
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 7 deletions.
8 changes: 7 additions & 1 deletion core_lib/src/interface/editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -914,9 +914,15 @@ KeyFrame* Editor::addKeyFrame(const int layerNumber, int frameIndex)
const bool ok = layer->addNewKeyFrameAt(frameIndex);
Q_ASSERT(ok); // We already ensured that there is no keyframe at frameIndex, so this should always succeed
scrubTo(frameIndex); // currentFrameChanged() emit inside.

const UndoSaveState* state = undoRedo()->state(UndoRedoRecordType::KEYFRAME_ADD);
emit frameModified(frameIndex);
layers()->notifyAnimationLengthChanged();
return layer->getKeyFrameAt(frameIndex);
KeyFrame* newFrame = layer->getKeyFrameAt(frameIndex);

undoRedo()->record(state, tr("Add frame"));

return newFrame;
}

void Editor::removeKey()
Expand Down
71 changes: 71 additions & 0 deletions core_lib/src/interface/undoredocommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ void KeyFrameRemoveCommand::undo()
UndoRedoCommand::undo();

Layer* layer = editor()->layers()->findLayerById(undoLayerId);
if (layer == nullptr) {
// Until we support layer deletion recovery, we mark the command as
// obsolete as soon as it's been
return setObsolete(true);
}

layer->addKeyFrame(undoKeyFrame->pos(), undoKeyFrame->clone());

Expand All @@ -86,6 +91,61 @@ void KeyFrameRemoveCommand::redo()
editor()->scrubTo(redoPosition);
}

KeyFrameAddCommand::KeyFrameAddCommand(int undoPosition,
int undoLayerId,
const QString &description,
Editor *editor,
QUndoCommand *parent)
: UndoRedoCommand(editor, parent)
{
this->undoPosition = undoPosition;
this->undoLayerId = undoLayerId;

this->redoLayerId = editor->layers()->currentLayer()->id();
this->redoPosition = editor->currentFrame();

setText(description);
}

KeyFrameAddCommand::~KeyFrameAddCommand()
{
}

void KeyFrameAddCommand::undo()
{
UndoRedoCommand::undo();

Layer* layer = editor()->layers()->findLayerById(undoLayerId);
if (layer == nullptr) {
// Until we support layer deletion recovery, we mark the command as
// obsolete as soon as it's been
return setObsolete(true);
}

layer->removeKeyFrame(undoPosition);

emit editor()->frameModified(undoPosition);
editor()->layers()->notifyAnimationLengthChanged();
editor()->layers()->setCurrentLayer(layer);
editor()->scrubTo(undoPosition);
}

void KeyFrameAddCommand::redo()
{
UndoRedoCommand::redo();

// Ignore automatic redo when added to undo stack
if (isFirstRedo()) { setFirstRedo(false); return; }

Layer* layer = editor()->layers()->findLayerById(redoLayerId);
layer->addNewKeyFrameAt(redoPosition);

emit editor()->frameModified(redoPosition);
editor()->layers()->notifyAnimationLengthChanged();
editor()->layers()->setCurrentLayer(layer);
editor()->scrubTo(redoPosition);
}

BitmapReplaceCommand::BitmapReplaceCommand(const BitmapImage* undoBitmap,
const int undoLayerId,
const QString& description,
Expand All @@ -109,6 +169,12 @@ void BitmapReplaceCommand::undo()
UndoRedoCommand::undo();

Layer* layer = editor()->layers()->findLayerById(undoLayerId);
if (layer == nullptr) {
// Until we support layer deletion recovery, we mark the command as
// obsolete as soon as it's been
return setObsolete(true);
}

static_cast<LayerBitmap*>(layer)->replaceKeyFrame(&undoBitmap);

editor()->scrubTo(undoBitmap.pos());
Expand Down Expand Up @@ -149,6 +215,11 @@ void VectorReplaceCommand::undo()
UndoRedoCommand::undo();

Layer* layer = editor()->layers()->findLayerById(undoLayerId);
if (layer == nullptr) {
// Until we support layer deletion recovery, we mark the command as
// obsolete as soon as it's been
return setObsolete(true);
}

static_cast<LayerVector*>(layer)->replaceKeyFrame(&undoVector);

Expand Down
27 changes: 25 additions & 2 deletions core_lib/src/interface/undoredocommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class UndoRedoCommand : public QUndoCommand
~UndoRedoCommand() override;

protected:
Editor* editor() { return mEditor; }
Editor* editor() const { return mEditor; }

bool isFirstRedo() const { return mIsFirstRedo; }
void setFirstRedo(const bool state) { mIsFirstRedo = state; }
Expand Down Expand Up @@ -73,7 +73,30 @@ class KeyFrameRemoveCommand : public UndoRedoCommand
int redoLayerId = 0;

KeyFrame* undoKeyFrame = nullptr;
int redoPosition;
int redoPosition = 0;
};

class KeyFrameAddCommand : public UndoRedoCommand
{
public:
KeyFrameAddCommand(int undoPosition,
int undoLayerId,
const QString& description,
Editor* editor,
QUndoCommand* parent = nullptr
);
~KeyFrameAddCommand();

void undo() override;
void redo() override;

private:

int undoLayerId = 0;
int redoLayerId = 0;

int undoPosition = 0;
int redoPosition = 0;
};

class BitmapReplaceCommand : public UndoRedoCommand
Expand Down
2 changes: 1 addition & 1 deletion core_lib/src/managers/layermanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Layer* LayerManager::findLayerByName(QString sName, Layer::LAYER_TYPE type)
return object()->findLayerByName(sName, type);
}

Layer* LayerManager::findLayerById(int layerId)
Layer* LayerManager::findLayerById(int layerId) const
{
return object()->findLayerById(layerId);
}
Expand Down
2 changes: 1 addition & 1 deletion core_lib/src/managers/layermanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class LayerManager : public BaseManager
Layer* getLayer(int index);
LayerCamera* getCameraLayerBelow(int layerIndex) const;
Layer* findLayerByName(QString sName, Layer::LAYER_TYPE type = Layer::UNDEFINED);
Layer* findLayerById(int layerId);
Layer* findLayerById(int layerId) const;
Layer* getLastCameraLayer();
int currentLayerIndex();
void setCurrentLayer(int nIndex);
Expand Down
17 changes: 16 additions & 1 deletion core_lib/src/managers/undoredomanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ void UndoRedoManager::record(const UndoSaveState*& undoState, const QString& des
removeKeyFrame(*undoState, description);
break;
}
case UndoRedoRecordType::KEYFRAME_ADD: {
addKeyFrame(*undoState, description);
break;
}
default: {
QString reason("Unhandled case for: ");
reason.append(description);
Expand Down Expand Up @@ -154,6 +158,15 @@ void UndoRedoManager::removeKeyFrame(const UndoSaveState& undoState, const QStri
pushCommand(element);
}

void UndoRedoManager::addKeyFrame(const UndoSaveState& undoState, const QString& description)
{
KeyFrameAddCommand* element = new KeyFrameAddCommand(undoState.currentFrameIndex,
undoState.layerId,
description,
editor());
pushCommand(element);
}

void UndoRedoManager::replaceKeyFrame(const UndoSaveState& undoState, const QString& description)
{
if (undoState.layerType == Layer::BITMAP) {
Expand Down Expand Up @@ -217,10 +230,11 @@ const UndoSaveState* UndoRedoManager::state(UndoRedoRecordType recordType) const

switch (recordType)
{
case UndoRedoRecordType::KEYFRAME_ADD:
case UndoRedoRecordType::KEYFRAME_MODIFY:
case UndoRedoRecordType::KEYFRAME_REMOVE: {
return savedKeyFrameState(recordType);
default:
case UndoRedoRecordType::INVALID:
return nullptr;
}
}
Expand All @@ -234,6 +248,7 @@ const UndoSaveState* UndoRedoManager::savedKeyFrameState(const UndoRedoRecordTyp
const Layer* layer = editor()->layers()->currentLayer();
undoSaveState->layerType = layer->type();
undoSaveState->layerId = layer->id();
undoSaveState->currentFrameIndex = editor()->currentFrame();

if (layer->type() == Layer::BITMAP || layer->type() == Layer::VECTOR) {
auto selectMan = editor()->select();
Expand Down
4 changes: 3 additions & 1 deletion core_lib/src/managers/undoredomanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class UndoRedoCommand;
enum class UndoRedoRecordType {
KEYFRAME_MODIFY, // Any modification that involve a keyframe
KEYFRAME_REMOVE, // Removing a keyframe
// KEYFRAME_ADD, // Adding a keyframe
KEYFRAME_ADD, // Adding a keyframe
// SCRUB_LAYER, // Scrubbing layer
// SCRUB_KEYFRAME, // Scrubbing keyframe
INVALID
Expand Down Expand Up @@ -77,6 +77,7 @@ struct SelectionSaveState {
/// whatever states that needs to be stored temporarily.
struct UndoSaveState {
int layerId = 0;
int currentFrameIndex = 0;
Layer::LAYER_TYPE layerType = Layer::UNDEFINED;

std::unique_ptr<KeyFrame> keyframe = nullptr;
Expand Down Expand Up @@ -154,6 +155,7 @@ class UndoRedoManager : public BaseManager
void replaceBitmap(const UndoSaveState& undoState, const QString& description);
void replaceVector(const UndoSaveState& undoState, const QString& description);

void addKeyFrame(const UndoSaveState& undoState, const QString& description);
void removeKeyFrame(const UndoSaveState& undoState, const QString& description);

const UndoSaveState* savedKeyFrameState(const UndoRedoRecordType& type) const;
Expand Down

0 comments on commit cf4b62e

Please sign in to comment.