Only include relevant frames in the timelapse animation

This commit is contained in:
Marcus Huderle 2021-01-19 20:21:15 -06:00
parent c354142f1b
commit 9439dc76d2
4 changed files with 103 additions and 13 deletions

View file

@ -13,7 +13,7 @@ class DraggablePixmapItem;
class Editor;
enum CommandId {
ID_PaintMetatile,
ID_PaintMetatile = 0,
ID_BucketFillMetatile,
ID_MagicFillMetatile,
ID_ShiftMetatiles,
@ -30,7 +30,11 @@ enum CommandId {
ID_EventDuplicate,
};
#define IDMask_EventType_Object (1 << 8)
#define IDMask_EventType_Warp (1 << 9)
#define IDMask_EventType_BG (1 << 10)
#define IDMask_EventType_Trigger (1 << 11)
#define IDMask_EventType_Heal (1 << 12)
/// Implements a command to commit metatile paint actions
/// onto the map using the pencil tool.
@ -240,7 +244,7 @@ public:
void redo() override;
bool mergeWith(const QUndoCommand *command) override;
int id() const override { return CommandId::ID_EventMove; }
int id() const override;
private:
QList<Event *> events;
@ -259,8 +263,9 @@ public:
int deltaX, int deltaY, unsigned actionId,
QUndoCommand *parent = nullptr);
~EventShift();
int id() const override { return CommandId::ID_EventShift; }
int id() const override;
private:
QList<Event *> events;
};
@ -277,7 +282,7 @@ public:
void redo() override;
bool mergeWith(const QUndoCommand *) override { return false; }
int id() const override { return CommandId::ID_EventCreate; }
int id() const override;
private:
Map *map;
@ -300,7 +305,7 @@ public:
void redo() override;
bool mergeWith(const QUndoCommand *) override { return false; }
int id() const override { return CommandId::ID_EventDelete; }
int id() const override;
private:
Editor *editor;
@ -322,7 +327,7 @@ public:
void redo() override;
bool mergeWith(const QUndoCommand *) override { return false; }
int id() const override { return CommandId::ID_EventDuplicate; }
int id() const override;
private:
Map *map;

View file

@ -53,6 +53,7 @@ private:
void saveImage();
QPixmap getStitchedImage(QProgressDialog *progress, bool includeBorder);
QPixmap getFormattedMapPixmap(Map *map, bool ignoreBorder);
bool historyItemAppliesToFrame(const QUndoCommand *command);
private slots:
void on_checkBox_Objects_stateChanged(int state);

View file

@ -6,7 +6,26 @@
#include <QDebug>
int getEventTypeMask(QList<Event *> events) {
int eventTypeMask = 0;
for (auto event : events) {
if (event->get("event_type") == EventType::Object) {
eventTypeMask |= IDMask_EventType_Object;
} else if (event->get("event_type") == EventType::Warp) {
eventTypeMask |= IDMask_EventType_Warp;
} else if (event->get("event_type") == EventType::Trigger ||
event->get("event_type") == EventType::WeatherTrigger) {
eventTypeMask |= IDMask_EventType_Trigger;
} else if (event->get("event_type") == EventType::Sign ||
event->get("event_type") == EventType::HiddenItem ||
event->get("event_type") == EventType::SecretBase) {
eventTypeMask |= IDMask_EventType_BG;
} else if (event->get("event_type") == EventType::HealLocation) {
eventTypeMask |= IDMask_EventType_Heal;
}
}
return eventTypeMask;
}
void renderMapBlocks(Map *map, bool ignoreCache = false) {
map->mapItem->draw(ignoreCache);
@ -305,6 +324,10 @@ bool EventMove::mergeWith(const QUndoCommand *command) {
return true;
}
int EventMove::id() const {
return CommandId::ID_EventMove | getEventTypeMask(events);
}
/******************************************************************************
************************************************************************
******************************************************************************/
@ -313,11 +336,16 @@ EventShift::EventShift(QList<Event *> events,
int deltaX, int deltaY, unsigned actionId,
QUndoCommand *parent)
: EventMove(events, deltaX, deltaY, actionId, parent) {
this->events = events;
setText("Shift Events");
}
EventShift::~EventShift() {}
int EventShift::id() const {
return CommandId::ID_EventShift | getEventTypeMask(events);
}
/******************************************************************************
************************************************************************
******************************************************************************/
@ -360,6 +388,10 @@ void EventCreate::undo() {
QUndoCommand::undo();
}
int EventCreate::id() const {
return CommandId::ID_EventCreate | getEventTypeMask(QList<Event*>({this->event}));
}
/******************************************************************************
************************************************************************
******************************************************************************/
@ -418,6 +450,10 @@ void EventDelete::undo() {
QUndoCommand::undo();
}
int EventDelete::id() const {
return CommandId::ID_EventDelete | getEventTypeMask(this->selectedEvents);
}
/******************************************************************************
************************************************************************
******************************************************************************/
@ -471,6 +507,10 @@ void EventDuplicate::undo() {
QUndoCommand::undo();
}
int EventDuplicate::id() const {
return CommandId::ID_EventDuplicate | getEventTypeMask(this->selectedEvents);
}
/******************************************************************************
************************************************************************
******************************************************************************/

View file

@ -1,6 +1,7 @@
#include "mapimageexporter.h"
#include "ui_mapimageexporter.h"
#include "qgifimage.h"
#include "editcommands.h"
#include <QFileDialog>
#include <QMatrix>
@ -99,8 +100,8 @@ void MapImageExporter::saveImage() {
int maxWidth = this->map->getWidth() * 16;
int maxHeight = this->map->getHeight() * 16;
if (showBorder) {
maxWidth += STITCH_MODE_BORDER_DISTANCE * 16;
maxHeight += STITCH_MODE_BORDER_DISTANCE * 16;
maxWidth += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
maxHeight += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
}
// Rewind to the specified start of the map edit history.
int i = 0;
@ -110,8 +111,8 @@ void MapImageExporter::saveImage() {
int width = this->map->getWidth() * 16;
int height = this->map->getHeight() * 16;
if (showBorder) {
width += STITCH_MODE_BORDER_DISTANCE * 16;
height += STITCH_MODE_BORDER_DISTANCE * 16;
width += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
height += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
}
if (width > maxWidth) {
maxWidth = width;
@ -136,6 +137,11 @@ void MapImageExporter::saveImage() {
}
return;
}
while (this->map->editHistory.canRedo() &&
!historyItemAppliesToFrame(this->map->editHistory.command(this->map->editHistory.index()))) {
i--;
this->map->editHistory.redo();
}
progress.setValue(progress.maximum() - i);
QPixmap pixmap = this->getFormattedMapPixmap(this->map, !this->showBorder);
if (pixmap.width() < maxWidth || pixmap.height() < maxHeight) {
@ -151,6 +157,11 @@ void MapImageExporter::saveImage() {
if (i > 0) {
i--;
this->map->editHistory.redo();
while (this->map->editHistory.canRedo() &&
!historyItemAppliesToFrame(this->map->editHistory.command(this->map->editHistory.index()))) {
i--;
this->map->editHistory.redo();
}
}
}
}
@ -165,6 +176,39 @@ void MapImageExporter::saveImage() {
}
}
bool MapImageExporter::historyItemAppliesToFrame(const QUndoCommand *command) {
switch (command->id() & 0xFF) {
case CommandId::ID_PaintMetatile:
case CommandId::ID_BucketFillMetatile:
case CommandId::ID_MagicFillMetatile:
case CommandId::ID_ShiftMetatiles:
case CommandId::ID_ResizeMap:
case CommandId::ID_ScriptEditMap:
return true;
case CommandId::ID_PaintCollision:
case CommandId::ID_BucketFillCollision:
case CommandId::ID_MagicFillCollision:
return this->showCollision;
case CommandId::ID_PaintBorder:
return this->showBorder;
case CommandId::ID_EventMove:
case CommandId::ID_EventShift:
case CommandId::ID_EventCreate:
case CommandId::ID_EventDelete:
case CommandId::ID_EventDuplicate: {
bool eventTypeIsApplicable =
(this->showObjects && (command->id() & IDMask_EventType_Object) != 0)
|| (this->showWarps && (command->id() & IDMask_EventType_Warp) != 0)
|| (this->showBGs && (command->id() & IDMask_EventType_BG) != 0)
|| (this->showTriggers && (command->id() & IDMask_EventType_Trigger) != 0)
|| (this->showHealSpots && (command->id() & IDMask_EventType_Heal) != 0);
return eventTypeIsApplicable;
}
default:
return false;
}
}
struct StitchedMap {
int x;
int y;