Refactor Editor's methods to move their code into another component

By moving the code of these methods we enable automated testing of some functionality that depends of the functionality but not depends of the Editor's GUI.
This commit is contained in:
Martín Capello 2021-05-19 16:36:43 -03:00
parent 34250a145f
commit ab58deaa45
4 changed files with 126 additions and 63 deletions

View File

@ -147,6 +147,7 @@ Editor::Editor(Doc* document, EditorFlags flags)
, m_layer(m_sprite->root()->firstLayer())
, m_frame(frame_t(0))
, m_docPref(Preferences::instance().document(document))
, m_tiledModeHelper(app::TiledModeHelper(m_docPref.tiled.mode(), m_sprite))
, m_brushPreview(this)
, m_toolLoopModifiers(tools::ToolLoopModifiers::kNone)
, m_padding(0, 0)
@ -2222,6 +2223,8 @@ void Editor::onTiledModeChange()
screenPos = editorToScreen(spritePos);
centerInSpritePoint(spritePos);
m_tiledModeHelper.mode(m_docPref.tiled.mode());
}
void Editor::onShowExtrasChange()
@ -2810,77 +2813,23 @@ gfx::Point Editor::calcExtraPadding(const Projection& proj)
gfx::Size Editor::canvasSize() const
{
gfx::Size sz(m_sprite->width(),
m_sprite->height());
if (int(m_docPref.tiled.mode()) & int(filters::TiledMode::X_AXIS)) {
sz.w += sz.w*2;
}
if (int(m_docPref.tiled.mode()) & int(filters::TiledMode::Y_AXIS)) {
sz.h += sz.h*2;
}
return sz;
return m_tiledModeHelper.canvasSize();
}
gfx::Point Editor::mainTilePosition() const
{
gfx::Point pt(0, 0);
if (int(m_docPref.tiled.mode()) & int(filters::TiledMode::X_AXIS)) {
pt.x += m_sprite->width();
}
if (int(m_docPref.tiled.mode()) & int(filters::TiledMode::Y_AXIS)) {
pt.y += m_sprite->height();
}
return pt;
return m_tiledModeHelper.mainTilePosition();
}
void Editor::expandRegionByTiledMode(gfx::Region& rgn,
const bool withProj) const
{
gfx::Region tile = rgn;
const bool xTiled = (int(m_docPref.tiled.mode()) & int(filters::TiledMode::X_AXIS));
const bool yTiled = (int(m_docPref.tiled.mode()) & int(filters::TiledMode::Y_AXIS));
int w = m_sprite->width();
int h = m_sprite->height();
if (withProj) {
w = m_proj.applyX(w);
h = m_proj.applyY(h);
}
if (xTiled) {
tile.offset(w, 0); rgn |= tile;
tile.offset(w, 0); rgn |= tile;
tile.offset(-2*w, 0);
}
if (yTiled) {
tile.offset(0, h); rgn |= tile;
tile.offset(0, h); rgn |= tile;
tile.offset(0, -2*h);
}
if (xTiled && yTiled) {
tile.offset(w, h); rgn |= tile;
tile.offset(w, 0); rgn |= tile;
tile.offset(-w, h); rgn |= tile;
tile.offset(w, 0); rgn |= tile;
}
m_tiledModeHelper.expandRegionByTiledMode(rgn, withProj ? &m_proj : nullptr);
}
void Editor::collapseRegionByTiledMode(gfx::Region& rgn) const
{
auto canvasSize = this->canvasSize();
rgn &= gfx::Region(gfx::Rect(canvasSize));
const int sprW = m_sprite->width();
const int sprH = m_sprite->height();
gfx::Region newRgn;
for (int v=0; v<canvasSize.h; v+=sprH) {
for (int u=0; u<canvasSize.w; u+=sprW) {
gfx::Region tmp(gfx::Rect(u, v, sprW, sprH));
tmp &= rgn;
tmp.offset(-u, -v);
newRgn |= tmp;
}
}
rgn = newRgn;
m_tiledModeHelper.collapseRegionByTiledMode(rgn);
}
bool Editor::isMovingPixels() const

View File

@ -22,6 +22,7 @@
#include "app/ui/editor/editor_state.h"
#include "app/ui/editor/editor_states_history.h"
#include "app/ui/tile_source.h"
#include "app/util/tiled_mode.h"
#include "doc/algorithm/flip_type.h"
#include "doc/frame.h"
#include "doc/image_buffer.h"
@ -403,6 +404,8 @@ namespace app {
frame_t m_frame; // Active frame in the editor
render::Projection m_proj; // Zoom/pixel ratio in the editor
DocumentPreferences& m_docPref;
// Helper functions affected by the current Tiled Mode.
app::TiledModeHelper m_tiledModeHelper;
// Brush preview
BrushPreview m_brushPreview;

View File

@ -473,6 +473,7 @@ class ToolLoopImpl : public ToolLoopBase,
std::unique_ptr<ExpandCelCanvas> m_expandCelCanvas;
Image* m_floodfillSrcImage;
bool m_saveLastPoint;
app::TiledModeHelper m_tiledModeHelper;
public:
ToolLoopImpl(Editor* editor,
@ -493,6 +494,7 @@ public:
ModifyDocument))
, m_floodfillSrcImage(nullptr)
, m_saveLastPoint(saveLastPoint)
, m_tiledModeHelper(m_docPref.tiled.mode(), m_sprite)
{
if (m_pointShape->isFloodFill()) {
if (m_tilesMode) {
@ -766,7 +768,7 @@ public:
getPointShape()->getModifiedArea(this, pos.x, pos.y, r);
gfx::Region rgn(r);
m_editor->collapseRegionByTiledMode(rgn);
m_tiledModeHelper.collapseRegionByTiledMode(rgn);
for (auto a : rgn) {
ImageRef i(Image::create(getSrcImage()->pixelFormat(), a.w, a.h));
@ -834,10 +836,10 @@ private:
return;
if (int(getTiledMode()) & int(TiledMode::X_AXIS)) {
result.x %= m_editor->canvasSize().w;
result.x %= m_tiledModeHelper.canvasSize().w;
}
if (int(getTiledMode()) & int(TiledMode::Y_AXIS)) {
result.y %= m_editor->canvasSize().h;
result.y %= m_tiledModeHelper.canvasSize().h;
}
gfx::Rect r;
@ -845,12 +847,12 @@ private:
if (r.x < 0)
result.x += m_sprite->width();
else if (r.x2() > m_editor->canvasSize().w)
else if (r.x2() > m_tiledModeHelper.canvasSize().w)
result.x -= m_sprite->width();
if (r.y < 0)
result.y += m_sprite->height();
else if (r.y2() > m_editor->canvasSize().h)
else if (r.y2() > m_tiledModeHelper.canvasSize().h)
result.y -= m_sprite->height();
}
};

109
src/app/util/tiled_mode.h Normal file
View File

@ -0,0 +1,109 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_TILED_MODE_H_INCLUDED
#define APP_TILED_MODE_H_INCLUDED
#pragma once
#include "filters/tiled_mode.h"
#include "app/doc.h"
#include "gfx/region.h"
#include "render/projection.h"
namespace app {
class TiledModeHelper {
public:
TiledModeHelper(const filters::TiledMode mode, const doc::Sprite* canvas) :
m_mode(mode),
m_canvas(canvas) {
}
~TiledModeHelper() {}
void mode(const filters::TiledMode mode) {
m_mode = mode;
}
gfx::Size canvasSize() const {
gfx::Size sz(m_canvas->width(),
m_canvas->height());
if (int(m_mode) & int(filters::TiledMode::X_AXIS)) {
sz.w += sz.w * 2;
}
if (int(m_mode) & int(filters::TiledMode::Y_AXIS)) {
sz.h += sz.h * 2;
}
return sz;
}
gfx::Point mainTilePosition() const {
gfx::Point pt(0, 0);
if (int(m_mode) & int(filters::TiledMode::X_AXIS)) {
pt.x += m_canvas->width();
}
if (int(m_mode) & int(filters::TiledMode::Y_AXIS)) {
pt.y += m_canvas->height();
}
return pt;
}
void expandRegionByTiledMode(gfx::Region& rgn,
const render::Projection* proj = nullptr) const {
gfx::Region tile = rgn;
const bool xTiled = (int(m_mode) & int(filters::TiledMode::X_AXIS));
const bool yTiled = (int(m_mode) & int(filters::TiledMode::Y_AXIS));
int w = m_canvas->width();
int h = m_canvas->height();
if (proj) {
w = proj->applyX(w);
h = proj->applyY(h);
}
if (xTiled) {
tile.offset(w, 0); rgn |= tile;
tile.offset(w, 0); rgn |= tile;
tile.offset(-2 * w, 0);
}
if (yTiled) {
tile.offset(0, h); rgn |= tile;
tile.offset(0, h); rgn |= tile;
tile.offset(0, -2 * h);
}
if (xTiled && yTiled) {
tile.offset(w, h); rgn |= tile;
tile.offset(w, 0); rgn |= tile;
tile.offset(-w, h); rgn |= tile;
tile.offset(w, 0); rgn |= tile;
}
}
void collapseRegionByTiledMode(gfx::Region& rgn) const {
auto canvasSize = this->canvasSize();
rgn &= gfx::Region(gfx::Rect(canvasSize));
const int sprW = m_canvas->width();
const int sprH = m_canvas->height();
gfx::Region newRgn;
for (int v = 0; v < canvasSize.h; v += sprH) {
for (int u = 0; u < canvasSize.w; u += sprW) {
gfx::Region tmp(gfx::Rect(u, v, sprW, sprH));
tmp &= rgn;
tmp.offset(-u, -v);
newRgn |= tmp;
}
}
rgn = newRgn;
}
private:
filters::TiledMode m_mode;
const doc::Sprite* m_canvas;
};
} // namespace app
#endif