mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 13:21:34 +00:00
Add possibility to paint with tiles
This commit is contained in:
parent
fbe2f8645d
commit
d0c95cf46f
@ -100,6 +100,9 @@ doc::color_t color_utils::color_for_image(const app::Color& color, PixelFormat f
|
||||
case IMAGE_INDEXED:
|
||||
c = color.getIndex();
|
||||
break;
|
||||
case IMAGE_TILEMAP:
|
||||
c = color.getIndex(); // TODO Add app::Color::getTile() ?
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
@ -122,6 +125,9 @@ doc::color_t color_utils::color_for_image_without_alpha(const app::Color& color,
|
||||
case IMAGE_INDEXED:
|
||||
c = color.getIndex();
|
||||
break;
|
||||
case IMAGE_TILEMAP:
|
||||
c = color.getIndex(); // TODO Add app::Color::getTile() ?
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
@ -165,6 +171,9 @@ doc::color_t color_utils::color_for_target_mask(const app::Color& color, const C
|
||||
c = get_current_palette()->findBestfit(r, g, b, a, mask);
|
||||
}
|
||||
break;
|
||||
case IMAGE_TILEMAP:
|
||||
c = color.getIndex(); // TODO Add app::Color::getTile() ?
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2020 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -25,12 +25,15 @@ public:
|
||||
protected:
|
||||
bool onChecked(Context* context) override {
|
||||
auto colorBar = ColorBar::instance();
|
||||
return colorBar->inTilesMode();
|
||||
return (colorBar->tilemapMode() == TilemapMode::Tiles);
|
||||
}
|
||||
|
||||
void onExecute(Context* context) override {
|
||||
auto colorBar = ColorBar::instance();
|
||||
colorBar->setTilesMode(!colorBar->inTilesMode());
|
||||
colorBar->setTilemapMode(
|
||||
colorBar->tilemapMode() == TilemapMode::Pixels ?
|
||||
TilemapMode::Tiles:
|
||||
TilemapMode::Pixels);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -20,21 +21,29 @@ ExtraCel::ExtraCel()
|
||||
{
|
||||
}
|
||||
|
||||
void ExtraCel::create(doc::Sprite* sprite,
|
||||
void ExtraCel::create(const TilemapMode tilemapMode,
|
||||
doc::Sprite* sprite,
|
||||
const gfx::Rect& bounds,
|
||||
doc::frame_t frame,
|
||||
int opacity)
|
||||
const gfx::Size& imageSize,
|
||||
const doc::frame_t frame,
|
||||
const int opacity)
|
||||
{
|
||||
ASSERT(sprite);
|
||||
|
||||
doc::PixelFormat pixelFormat;
|
||||
if (tilemapMode == TilemapMode::Tiles)
|
||||
pixelFormat = doc::IMAGE_TILEMAP;
|
||||
else
|
||||
pixelFormat = sprite->pixelFormat();
|
||||
|
||||
if (!m_image ||
|
||||
m_image->pixelFormat() != sprite->pixelFormat() ||
|
||||
m_image->width() != bounds.w ||
|
||||
m_image->height() != bounds.h) {
|
||||
m_image->pixelFormat() != pixelFormat ||
|
||||
m_image->width() != imageSize.w ||
|
||||
m_image->height() != imageSize.h) {
|
||||
if (!m_imageBuffer)
|
||||
m_imageBuffer.reset(new doc::ImageBuffer(1));
|
||||
doc::Image* newImage = doc::Image::create(sprite->pixelFormat(),
|
||||
bounds.w, bounds.h,
|
||||
doc::Image* newImage = doc::Image::create(pixelFormat,
|
||||
imageSize.w, imageSize.h,
|
||||
m_imageBuffer);
|
||||
m_image.reset(newImage);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -9,6 +9,7 @@
|
||||
#define APP_EXTRA_CEL_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/tilemap_mode.h"
|
||||
#include "base/disable_copying.h"
|
||||
#include "doc/blend_mode.h"
|
||||
#include "doc/cel.h"
|
||||
@ -30,7 +31,12 @@ namespace app {
|
||||
public:
|
||||
ExtraCel();
|
||||
|
||||
void create(doc::Sprite* sprite, const gfx::Rect& bounds, doc::frame_t frame, int opacity);
|
||||
void create(const TilemapMode tilemapMode,
|
||||
doc::Sprite* sprite,
|
||||
const gfx::Rect& bounds,
|
||||
const gfx::Size& imageSize,
|
||||
const doc::frame_t frame,
|
||||
const int opacity);
|
||||
|
||||
render::ExtraType type() const { return m_type; }
|
||||
void setType(render::ExtraType type) { m_type = type; }
|
||||
|
@ -35,15 +35,7 @@ RgbMap* Site::rgbMap() const
|
||||
return (m_sprite ? m_sprite->rgbMap(m_frame): nullptr);
|
||||
}
|
||||
|
||||
const Cel* Site::cel() const
|
||||
{
|
||||
if (m_layer)
|
||||
return m_layer->cel(m_frame);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Cel* Site::cel()
|
||||
Cel* Site::cel() const
|
||||
{
|
||||
if (m_layer)
|
||||
return m_layer->cel(m_frame);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "app/doc_range.h"
|
||||
#include "app/tilemap_mode.h"
|
||||
#include "app/tileset_mode.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/palette_picks.h"
|
||||
@ -52,6 +53,7 @@ namespace app {
|
||||
, m_sprite(nullptr)
|
||||
, m_layer(nullptr)
|
||||
, m_frame(0)
|
||||
, m_tilemapMode(TilemapMode::Pixels)
|
||||
, m_tilesetMode(TilesetMode::Manual) { }
|
||||
|
||||
const Focus focus() const { return m_focus; }
|
||||
@ -62,16 +64,11 @@ namespace app {
|
||||
bool inColorBar() const { return m_focus == InColorBar; }
|
||||
bool inTimeline() const { return (inLayers() || inFrames() || inCels()); }
|
||||
|
||||
const Doc* document() const { return m_document; }
|
||||
const doc::Sprite* sprite() const { return m_sprite; }
|
||||
const doc::Layer* layer() const { return m_layer; }
|
||||
Doc* document() const { return m_document; }
|
||||
doc::Sprite* sprite() const { return m_sprite; }
|
||||
doc::Layer* layer() const { return m_layer; }
|
||||
doc::frame_t frame() const { return m_frame; }
|
||||
const doc::Cel* cel() const;
|
||||
|
||||
Doc* document() { return m_document; }
|
||||
doc::Sprite* sprite() { return m_sprite; }
|
||||
doc::Layer* layer() { return m_layer; }
|
||||
doc::Cel* cel();
|
||||
doc::Cel* cel() const;
|
||||
const DocRange& range() const { return m_range; }
|
||||
|
||||
void focus(Focus focus) { m_focus = focus; }
|
||||
@ -112,8 +109,10 @@ namespace app {
|
||||
doc::Grid grid() const;
|
||||
gfx::Rect gridBounds() const;
|
||||
|
||||
void tilesetMode(const TilesetMode& mode) { m_tilesetMode = mode; }
|
||||
const TilesetMode& tilesetMode() const { return m_tilesetMode; }
|
||||
void tilemapMode(const TilemapMode mode) { m_tilemapMode = mode; }
|
||||
void tilesetMode(const TilesetMode mode) { m_tilesetMode = mode; }
|
||||
TilemapMode tilemapMode() const { return m_tilemapMode; }
|
||||
TilesetMode tilesetMode() const { return m_tilesetMode; }
|
||||
|
||||
private:
|
||||
Focus m_focus;
|
||||
@ -125,6 +124,7 @@ namespace app {
|
||||
doc::PalettePicks m_selectedColors;
|
||||
doc::PalettePicks m_selectedTiles;
|
||||
doc::SelectedObjects m_selectedSlices;
|
||||
TilemapMode m_tilemapMode;
|
||||
TilesetMode m_tilesetMode;
|
||||
};
|
||||
|
||||
|
21
src/app/tilemap_mode.h
Normal file
21
src/app/tilemap_mode.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Aseprite
|
||||
// Copyright (c) 2020 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_TILEMAP_MODE_H_INCLUDED
|
||||
#define APP_TILEMAP_MODE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace app {
|
||||
|
||||
// Should we edit the pixels or the tiles of the tilemap?
|
||||
enum class TilemapMode {
|
||||
Pixels, // Edit tile pixels
|
||||
Tiles, // Edit tiles
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -1,11 +1,11 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_TILES_MODE_H_INCLUDED
|
||||
#define APP_TILES_MODE_H_INCLUDED
|
||||
#ifndef APP_TILESET_MODE_H_INCLUDED
|
||||
#define APP_TILESET_MODE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace app {
|
||||
|
@ -158,7 +158,12 @@ public:
|
||||
break;
|
||||
}
|
||||
case Copy:
|
||||
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||
if (loop->getDstImage()->pixelFormat() == IMAGE_TILEMAP) {
|
||||
setProc(new CopyInkProcessing<TilemapTraits>(loop));
|
||||
}
|
||||
else {
|
||||
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||
}
|
||||
break;
|
||||
case LockAlpha:
|
||||
setProc(get_ink_proc<LockAlphaInkProcessing>(loop));
|
||||
|
@ -38,6 +38,24 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class TilePointShape : public PointShape {
|
||||
public:
|
||||
bool isPixel() override { return true; }
|
||||
|
||||
void transformPoint(ToolLoop* loop, const Stroke::Pt& pt) override {
|
||||
const doc::Grid& grid = loop->getGrid();
|
||||
gfx::Point newPos = grid.canvasToTile(pt.toPoint());
|
||||
|
||||
loop->getInk()->prepareForPointShape(loop, true, newPos.x, newPos.y);
|
||||
doInkHline(newPos.x, newPos.y, newPos.x, loop);
|
||||
}
|
||||
|
||||
void getModifiedArea(ToolLoop* loop, int x, int y, Rect& area) override {
|
||||
const doc::Grid& grid = loop->getGrid();
|
||||
area = grid.alignBounds(Rect(x, y, 1, 1));
|
||||
}
|
||||
};
|
||||
|
||||
class BrushPointShape : public PointShape {
|
||||
bool m_firstPoint;
|
||||
Brush* m_lastBrush;
|
||||
|
@ -92,6 +92,7 @@ const char* WellKnownIntertwiners::AsPixelPerfect = "as_pixel_perfect";
|
||||
|
||||
const char* WellKnownPointShapes::None = "none";
|
||||
const char* WellKnownPointShapes::Pixel = "pixel";
|
||||
const char* WellKnownPointShapes::Tile = "tile";
|
||||
const char* WellKnownPointShapes::Brush = "brush";
|
||||
const char* WellKnownPointShapes::FloodFill = "floodfill";
|
||||
const char* WellKnownPointShapes::Spray = "spray";
|
||||
@ -143,6 +144,7 @@ ToolBox::ToolBox()
|
||||
|
||||
m_pointshapers[WellKnownPointShapes::None] = new NonePointShape();
|
||||
m_pointshapers[WellKnownPointShapes::Pixel] = new PixelPointShape();
|
||||
m_pointshapers[WellKnownPointShapes::Tile] = new TilePointShape();
|
||||
m_pointshapers[WellKnownPointShapes::Brush] = new BrushPointShape();
|
||||
m_pointshapers[WellKnownPointShapes::FloodFill] = new FloodFillPointShape();
|
||||
m_pointshapers[WellKnownPointShapes::Spray] = new SprayPointShape();
|
||||
|
@ -78,6 +78,7 @@ namespace app {
|
||||
namespace WellKnownPointShapes {
|
||||
extern const char* None;
|
||||
extern const char* Pixel;
|
||||
extern const char* Tile;
|
||||
extern const char* Brush;
|
||||
extern const char* FloodFill;
|
||||
extern const char* Spray;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "doc/brush.h"
|
||||
#include "doc/color.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/grid.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
@ -182,6 +183,7 @@ namespace app {
|
||||
virtual bool getSnapToGrid() = 0;
|
||||
virtual bool isSelectingTiles() = 0;
|
||||
virtual bool getStopAtGrid() = 0; // For floodfill-like tools
|
||||
virtual const doc::Grid& getGrid() const = 0;
|
||||
virtual gfx::Rect getGridBounds() = 0;
|
||||
virtual bool isPixelConnectivityEightConnected() = 0;
|
||||
|
||||
|
@ -170,7 +170,7 @@ ColorBar::ColorBar(int align, TooltipManager* tooltipManager)
|
||||
, m_ascending(true)
|
||||
, m_lastButton(kButtonLeft)
|
||||
, m_editMode(false)
|
||||
, m_tilesMode(false)
|
||||
, m_tilemapMode(TilemapMode::Pixels)
|
||||
, m_tilesetMode(TilesetMode::Auto)
|
||||
, m_redrawTimer(250, this)
|
||||
, m_redrawAll(false)
|
||||
@ -388,6 +388,16 @@ void ColorBar::setBgColor(const app::Color& color)
|
||||
onColorButtonChange(color);
|
||||
}
|
||||
|
||||
doc::tile_index ColorBar::getFgTile() const
|
||||
{
|
||||
return m_fgColor.getColor().getIndex(); // TODO
|
||||
}
|
||||
|
||||
doc::tile_index ColorBar::getBgTile() const
|
||||
{
|
||||
return m_bgColor.getColor().getIndex(); // TODO
|
||||
}
|
||||
|
||||
PaletteView* ColorBar::getPaletteView()
|
||||
{
|
||||
return &m_paletteView;
|
||||
@ -485,28 +495,31 @@ void ColorBar::setEditMode(bool state)
|
||||
m_paletteView.deselect();
|
||||
}
|
||||
|
||||
bool ColorBar::inTilesMode() const
|
||||
TilemapMode ColorBar::tilemapMode() const
|
||||
{
|
||||
return
|
||||
(m_tilesMode &&
|
||||
m_tilesHBox.isVisible() &&
|
||||
(m_tilesHBox.isVisible() &&
|
||||
m_lastDocument &&
|
||||
m_lastDocument->sprite());
|
||||
m_lastDocument->sprite()) ? m_tilemapMode:
|
||||
TilemapMode::Pixels;
|
||||
}
|
||||
|
||||
void ColorBar::setTilesMode(bool state)
|
||||
void ColorBar::setTilemapMode(const TilemapMode mode)
|
||||
{
|
||||
const Site site = UIContext::instance()->activeSite();
|
||||
const bool isTilemap = (site.layer() && site.layer()->isTilemap());
|
||||
const bool editTiles = (mode == TilemapMode::Tiles);
|
||||
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||
ButtonSet::Item* item = m_tilesButton.getItem(0);
|
||||
|
||||
m_tilesMode = state;
|
||||
item->setHotColor(state ? theme->colors.editPalFace(): gfx::ColorNone);
|
||||
m_tilemapMode = mode;
|
||||
item->setHotColor(editTiles ?
|
||||
theme->colors.editPalFace():
|
||||
gfx::ColorNone);
|
||||
item->setMono(true);
|
||||
|
||||
if (state && isTilemap) {
|
||||
if (editTiles && isTilemap) {
|
||||
manager()->freeWidget(&m_paletteView);
|
||||
m_scrollablePalView.setVisible(false);
|
||||
m_scrollableTilesView.setVisible(true);
|
||||
@ -575,8 +588,8 @@ void ColorBar::onActiveSiteChange(const Site& site)
|
||||
}
|
||||
if (!isTilemap) {
|
||||
m_lastTilesetId = doc::NullId;
|
||||
if (m_tilesMode)
|
||||
setTilesMode(false);
|
||||
if (m_tilemapMode == TilemapMode::Tiles)
|
||||
setTilemapMode(TilemapMode::Pixels);
|
||||
}
|
||||
}
|
||||
|
||||
@ -679,7 +692,9 @@ void ColorBar::onPaletteButtonClick()
|
||||
void ColorBar::onTilesButtonClick()
|
||||
{
|
||||
m_tilesButton.deselectItems();
|
||||
setTilesMode(!inTilesMode());
|
||||
setTilemapMode(
|
||||
(tilemapMode() == TilemapMode::Pixels ? TilemapMode::Tiles:
|
||||
TilemapMode::Pixels));
|
||||
}
|
||||
|
||||
void ColorBar::onTilesetModeButtonClick()
|
||||
@ -885,7 +900,7 @@ void ColorBar::setTransparentIndex(int index)
|
||||
|
||||
void ColorBar::onPaletteViewChangeSize(int boxsize)
|
||||
{
|
||||
if (inTilesMode())
|
||||
if (tilemapMode() == TilemapMode::Tiles)
|
||||
Preferences::instance().colorBar.tilesBoxSize(boxsize);
|
||||
else
|
||||
Preferences::instance().colorBar.boxSize(boxsize);
|
||||
@ -1037,6 +1052,14 @@ void ColorBar::onTilesViewDragAndDrop(doc::Tileset* tileset,
|
||||
void ColorBar::onTilesViewIndexChange(int index, ui::MouseButton button)
|
||||
{
|
||||
// TODO show tools to stamp/draw/pick tiles
|
||||
|
||||
if (button == kButtonRight)
|
||||
setBgColor(app::Color::fromIndex(index));
|
||||
else if (button == kButtonLeft)
|
||||
setFgColor(app::Color::fromIndex(index));
|
||||
else if (button == kButtonMiddle) {
|
||||
// TODO ?
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBar::onFgColorChangeFromPreferences()
|
||||
@ -1323,7 +1346,7 @@ void ColorBar::onNewInputPriority(InputChainElement* element,
|
||||
return;
|
||||
|
||||
if (element != this) {
|
||||
if (m_tilesMode)
|
||||
if (m_tilemapMode == TilemapMode::Tiles)
|
||||
m_tilesView.deselect();
|
||||
else
|
||||
m_paletteView.deselect();
|
||||
@ -1332,7 +1355,7 @@ void ColorBar::onNewInputPriority(InputChainElement* element,
|
||||
|
||||
bool ColorBar::onCanCut(Context* ctx)
|
||||
{
|
||||
if (m_tilesMode)
|
||||
if (m_tilemapMode == TilemapMode::Tiles)
|
||||
return (m_tilesView.getSelectedEntriesCount() > 0);
|
||||
else
|
||||
return (m_paletteView.getSelectedEntriesCount() > 0);
|
||||
@ -1345,7 +1368,7 @@ bool ColorBar::onCanCopy(Context* ctx)
|
||||
|
||||
bool ColorBar::onCanPaste(Context* ctx)
|
||||
{
|
||||
if (m_tilesMode)
|
||||
if (m_tilemapMode == TilemapMode::Tiles)
|
||||
return (clipboard::get_current_format() == clipboard::ClipboardTiles);
|
||||
else
|
||||
return (clipboard::get_current_format() == clipboard::ClipboardPaletteEntries);
|
||||
@ -1358,7 +1381,7 @@ bool ColorBar::onCanClear(Context* ctx)
|
||||
|
||||
bool ColorBar::onCut(Context* ctx)
|
||||
{
|
||||
if (m_tilesMode) {
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
m_tilesView.cutToClipboard();
|
||||
showRemapTiles();
|
||||
}
|
||||
@ -1369,7 +1392,7 @@ bool ColorBar::onCut(Context* ctx)
|
||||
|
||||
bool ColorBar::onCopy(Context* ctx)
|
||||
{
|
||||
if (m_tilesMode)
|
||||
if (m_tilemapMode == TilemapMode::Tiles)
|
||||
m_tilesView.copyToClipboard();
|
||||
else
|
||||
m_paletteView.copyToClipboard();
|
||||
@ -1378,7 +1401,7 @@ bool ColorBar::onCopy(Context* ctx)
|
||||
|
||||
bool ColorBar::onPaste(Context* ctx)
|
||||
{
|
||||
if (m_tilesMode) {
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
m_tilesView.pasteFromClipboard();
|
||||
showRemapTiles();
|
||||
}
|
||||
@ -1389,7 +1412,7 @@ bool ColorBar::onPaste(Context* ctx)
|
||||
|
||||
bool ColorBar::onClear(Context* ctx)
|
||||
{
|
||||
if (m_tilesMode) {
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
m_tilesView.clearSelection();
|
||||
showRemapTiles();
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "app/context_observer.h"
|
||||
#include "app/doc_observer.h"
|
||||
#include "app/docs_observer.h"
|
||||
#include "app/tilemap_mode.h"
|
||||
#include "app/tileset_mode.h"
|
||||
#include "app/ui/button_set.h"
|
||||
#include "app/ui/color_button.h"
|
||||
@ -71,6 +72,9 @@ namespace app {
|
||||
void setFgColor(const app::Color& color);
|
||||
void setBgColor(const app::Color& color);
|
||||
|
||||
doc::tile_index getFgTile() const;
|
||||
doc::tile_index getBgTile() const;
|
||||
|
||||
PaletteView* getPaletteView();
|
||||
|
||||
ColorSelector getColorSelector() const;
|
||||
@ -81,8 +85,8 @@ namespace app {
|
||||
bool inEditMode() const;
|
||||
void setEditMode(bool state);
|
||||
|
||||
bool inTilesMode() const;
|
||||
void setTilesMode(bool state);
|
||||
TilemapMode tilemapMode() const;
|
||||
void setTilemapMode(const TilemapMode mode);
|
||||
|
||||
TilesetMode tilesetMode() const;
|
||||
void setTilesetMode(const TilesetMode mode);
|
||||
@ -234,7 +238,7 @@ namespace app {
|
||||
bool m_editMode;
|
||||
|
||||
// True if we should be putting/setting tiles.
|
||||
bool m_tilesMode;
|
||||
TilemapMode m_tilemapMode;
|
||||
TilesetMode m_tilesetMode;
|
||||
|
||||
// Timer to redraw editors after a palette change.
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "app/tools/point_shape.h"
|
||||
#include "app/tools/tool.h"
|
||||
#include "app/tools/tool_loop.h"
|
||||
#include "app/ui/color_bar.h"
|
||||
#include "app/ui/context_bar.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/editor/tool_loop_impl.h"
|
||||
@ -34,8 +35,8 @@
|
||||
#include "doc/image_impl.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "render/render.h"
|
||||
#include "os/display.h"
|
||||
#include "render/render.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/system.h"
|
||||
|
||||
@ -201,7 +202,12 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
|
||||
// Draw pixel/brush preview
|
||||
if (showPreview) {
|
||||
gfx::Rect origBrushBounds = (isFloodfill ? gfx::Rect(0, 0, 1, 1): brush->bounds());
|
||||
Site site = m_editor->getSite();
|
||||
|
||||
// TODO add support for "tile-brushes"
|
||||
gfx::Rect origBrushBounds =
|
||||
(isFloodfill || site.tilemapMode() == TilemapMode::Tiles ? gfx::Rect(0, 0, 1, 1):
|
||||
brush->bounds());
|
||||
gfx::Rect brushBounds = origBrushBounds;
|
||||
brushBounds.offset(spritePos);
|
||||
gfx::Rect extraCelBounds = brushBounds;
|
||||
@ -226,8 +232,17 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Rect extraCelBoundsInCanvas;
|
||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
||||
ASSERT(layer->isTilemap());
|
||||
extraCelBounds.setOrigin(site.grid().canvasToTile(extraCelBounds.origin()));
|
||||
extraCelBoundsInCanvas = site.grid().tileToCanvas(extraCelBounds);
|
||||
}
|
||||
else {
|
||||
extraCelBoundsInCanvas = extraCelBounds;
|
||||
}
|
||||
|
||||
// Create the extra cel to show the brush preview
|
||||
Site site = m_editor->getSite();
|
||||
Cel* cel = site.cel();
|
||||
|
||||
int t, opacity = 255;
|
||||
@ -236,7 +251,14 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
|
||||
if (!m_extraCel)
|
||||
m_extraCel.reset(new ExtraCel);
|
||||
m_extraCel->create(document->sprite(), extraCelBounds, site.frame(), opacity);
|
||||
|
||||
m_extraCel->create(
|
||||
site.tilemapMode(),
|
||||
document->sprite(),
|
||||
extraCelBoundsInCanvas,
|
||||
extraCelBounds.size(),
|
||||
site.frame(),
|
||||
opacity);
|
||||
m_extraCel->setType(render::ExtraType::NONE);
|
||||
m_extraCel->setBlendMode(
|
||||
(layer ? static_cast<LayerImage*>(layer)->blendMode():
|
||||
@ -252,7 +274,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
if (layer) {
|
||||
render::Render().renderLayer(
|
||||
extraImage, layer, site.frame(),
|
||||
gfx::Clip(0, 0, extraCelBounds),
|
||||
gfx::Clip(0, 0, extraCelBoundsInCanvas),
|
||||
BlendMode::SRC);
|
||||
|
||||
// This extra cel is a patch for the current layer/frame
|
||||
@ -279,7 +301,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
}
|
||||
|
||||
document->notifySpritePixelsModified(
|
||||
sprite, gfx::Region(m_lastBounds = extraCelBounds),
|
||||
sprite, gfx::Region(m_lastBounds = extraCelBoundsInCanvas),
|
||||
m_lastFrame = site.frame());
|
||||
|
||||
m_withRealPreview = true;
|
||||
|
@ -410,12 +410,16 @@ void Editor::getSite(Site* site) const
|
||||
}
|
||||
|
||||
if (m_layer && m_layer->isTilemap()) {
|
||||
TilesetMode mode = site->tilesetMode();
|
||||
TilemapMode tilemapMode = site->tilemapMode();
|
||||
TilesetMode tilesetMode = site->tilesetMode();
|
||||
const ColorBar* colorbar = ColorBar::instance();
|
||||
ASSERT(colorbar);
|
||||
if (colorbar)
|
||||
mode = colorbar->tilesetMode();
|
||||
site->tilesetMode(mode);
|
||||
if (colorbar) {
|
||||
tilemapMode = colorbar->tilemapMode();
|
||||
tilesetMode = colorbar->tilesetMode();
|
||||
}
|
||||
site->tilemapMode(tilemapMode);
|
||||
site->tilesetMode(tilesetMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -785,7 +785,14 @@ void PixelsMovement::redrawExtraImage(Transformation* transformation)
|
||||
if (!m_extraCel)
|
||||
m_extraCel.reset(new ExtraCel);
|
||||
|
||||
m_extraCel->create(m_document->sprite(), bounds, m_site.frame(), opacity);
|
||||
m_extraCel->create(
|
||||
m_site.tilemapMode(),
|
||||
m_document->sprite(),
|
||||
bounds,
|
||||
(m_site.tilemapMode() == TilemapMode::Tiles ? m_site.grid().tileToCanvas(bounds).size():
|
||||
bounds.size()),
|
||||
m_site.frame(),
|
||||
opacity);
|
||||
m_extraCel->setType(render::ExtraType::PATCH);
|
||||
m_extraCel->setBlendMode(m_site.layer()->isImage() ?
|
||||
static_cast<LayerImage*>(m_site.layer())->blendMode():
|
||||
|
@ -103,6 +103,7 @@ protected:
|
||||
bool m_contiguous;
|
||||
bool m_snapToGrid;
|
||||
bool m_isSelectingTiles;
|
||||
doc::Grid m_grid;
|
||||
gfx::Rect m_gridBounds;
|
||||
gfx::Point m_celOrigin;
|
||||
gfx::Point m_speed;
|
||||
@ -123,7 +124,8 @@ protected:
|
||||
tools::DynamicsOptions m_dynamics;
|
||||
|
||||
public:
|
||||
ToolLoopBase(Editor* editor, Site site,
|
||||
ToolLoopBase(Editor* editor,
|
||||
const Site& site,
|
||||
ToolLoopParams& params)
|
||||
: m_editor(editor)
|
||||
, m_tool(params.tool)
|
||||
@ -142,7 +144,8 @@ public:
|
||||
, m_contiguous(params.contiguous)
|
||||
, m_snapToGrid(m_docPref.grid.snap())
|
||||
, m_isSelectingTiles(false)
|
||||
, m_gridBounds(params.gridBounds)
|
||||
, m_grid(site.grid())
|
||||
, m_gridBounds(site.gridBounds())
|
||||
, m_button(params.button)
|
||||
, m_ink(params.ink->clone())
|
||||
, m_controller(params.controller)
|
||||
@ -150,7 +153,9 @@ public:
|
||||
, m_intertwine(m_tool->getIntertwine(m_button))
|
||||
, m_tracePolicy(m_tool->getTracePolicy(m_button))
|
||||
, m_symmetry(nullptr)
|
||||
, m_colorTarget(m_layer ? ColorTarget(m_layer):
|
||||
, m_colorTarget(site.tilemapMode() == TilemapMode::Tiles ? ColorTarget(ColorTarget::BackgroundLayer,
|
||||
IMAGE_TILEMAP, 0):
|
||||
m_layer ? ColorTarget(m_layer):
|
||||
ColorTarget(ColorTarget::BackgroundLayer,
|
||||
m_sprite->pixelFormat(),
|
||||
m_sprite->transparentColor()))
|
||||
@ -163,6 +168,11 @@ public:
|
||||
ASSERT(m_ink);
|
||||
ASSERT(m_controller);
|
||||
|
||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
||||
m_pointShape = App::instance()->toolBox()->getPointShapeById(
|
||||
tools::WellKnownPointShapes::Tile);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UI // TODO add dynamics support when UI is not enabled
|
||||
if (m_controller->isFreehand() &&
|
||||
!m_pointShape->isFloodFill() &&
|
||||
@ -309,6 +319,7 @@ public:
|
||||
== app::gen::PixelConnectivity::EIGHT_CONNECTED);
|
||||
}
|
||||
|
||||
const doc::Grid& getGrid() const override { return m_grid; }
|
||||
gfx::Rect getGridBounds() override { return m_gridBounds; }
|
||||
gfx::Point getCelOrigin() override { return m_celOrigin; }
|
||||
void setSpeed(const gfx::Point& speed) override { m_speed = speed; }
|
||||
@ -432,7 +443,7 @@ class ToolLoopImpl : public ToolLoopBase {
|
||||
|
||||
public:
|
||||
ToolLoopImpl(Editor* editor,
|
||||
Site site,
|
||||
const Site& site,
|
||||
Context* context,
|
||||
ToolLoopParams& params,
|
||||
const bool saveLastPoint)
|
||||
@ -691,9 +702,18 @@ tools::ToolLoop* create_tool_loop(
|
||||
const bool convertLineToFreehand,
|
||||
const bool selectTiles)
|
||||
{
|
||||
Site site = editor->getSite();
|
||||
|
||||
ToolLoopParams params;
|
||||
params.tool = editor->getCurrentEditorTool();
|
||||
params.ink = editor->getCurrentEditorInk();
|
||||
|
||||
// TODO add inks for tilemaps
|
||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
||||
if (!params.ink->isSelection())
|
||||
params.ink = App::instance()->toolBox()->getInkById(tools::WellKnownInks::PaintCopy);
|
||||
}
|
||||
|
||||
if (!params.tool || !params.ink)
|
||||
return nullptr;
|
||||
|
||||
@ -702,14 +722,6 @@ tools::ToolLoop* create_tool_loop(
|
||||
params.ink = params.tool->getInk(button == tools::Pointer::Left ? 0: 1);
|
||||
}
|
||||
|
||||
Site site = editor->getSite();
|
||||
|
||||
// Get grid bounds from the original site (as we call
|
||||
// site.layer(nullptr) in certain cases, we need to know if the
|
||||
// active layer is a tilemap, and in that case the grid bounds can
|
||||
// be different than the sprite grid bounds).
|
||||
params.gridBounds = site.gridBounds();
|
||||
|
||||
// For selection tools, we can use any layer (even without layers at
|
||||
// all), so we specify a nullptr here as the active layer. This is
|
||||
// used as a special case by the render::Render class to show the
|
||||
@ -750,11 +762,18 @@ tools::ToolLoop* create_tool_loop(
|
||||
|
||||
// Get fg/bg colors
|
||||
ColorBar* colorbar = ColorBar::instance();
|
||||
params.fg = colorbar->getFgColor();
|
||||
params.bg = colorbar->getBgColor();
|
||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
||||
params.fg = app::Color::fromIndex(colorbar->getFgTile()); // TODO Color::fromTileIndex?
|
||||
params.bg = app::Color::fromIndex(colorbar->getBgTile());
|
||||
}
|
||||
else {
|
||||
params.fg = colorbar->getFgColor();
|
||||
params.bg = colorbar->getBgColor();
|
||||
}
|
||||
|
||||
if (!params.fg.isValid() ||
|
||||
!params.bg.isValid()) {
|
||||
if (site.tilemapMode() == TilemapMode::Pixels &&
|
||||
(!params.fg.isValid() ||
|
||||
!params.bg.isValid())) {
|
||||
if (Preferences::instance().colorBar.showInvalidFgBgColorAlert()) {
|
||||
OptionalAlert::show(
|
||||
Preferences::instance().colorBar.showInvalidFgBgColorAlert,
|
||||
@ -817,9 +836,6 @@ tools::ToolLoop* create_tool_loop_for_script(
|
||||
if (!site.layer())
|
||||
return nullptr;
|
||||
|
||||
// TODO should gridBounds be specified by the caller?
|
||||
params.gridBounds = site.gridBounds();
|
||||
|
||||
try {
|
||||
// If we don't have the UI available, we reset the tools
|
||||
// preferences, so scripts that are executed in batch mode have a
|
||||
@ -849,10 +865,11 @@ class PreviewToolLoopImpl : public ToolLoopBase {
|
||||
public:
|
||||
PreviewToolLoopImpl(
|
||||
Editor* editor,
|
||||
const Site& site,
|
||||
ToolLoopParams& params,
|
||||
Image* image,
|
||||
const gfx::Point& celOrigin)
|
||||
: ToolLoopBase(editor, editor->getSite(), params)
|
||||
: ToolLoopBase(editor, site, params)
|
||||
, m_image(image)
|
||||
{
|
||||
m_celOrigin = celOrigin;
|
||||
@ -906,9 +923,19 @@ tools::ToolLoop* create_tool_loop_preview(
|
||||
Image* image,
|
||||
const gfx::Point& celOrigin)
|
||||
{
|
||||
Site site = editor->getSite();
|
||||
|
||||
ToolLoopParams params;
|
||||
params.tool = editor->getCurrentEditorTool();
|
||||
params.ink = editor->getCurrentEditorInk();
|
||||
|
||||
// TODO add inks for tilemaps
|
||||
if (site.tilemapMode() == TilemapMode::Tiles &&
|
||||
image->pixelFormat() == IMAGE_TILEMAP) {
|
||||
if (!params.ink->isSelection())
|
||||
params.ink = App::instance()->toolBox()->getInkById(tools::WellKnownInks::PaintCopy);
|
||||
}
|
||||
|
||||
if (!params.tool || !params.ink)
|
||||
return nullptr;
|
||||
|
||||
@ -922,8 +949,16 @@ tools::ToolLoop* create_tool_loop_preview(
|
||||
|
||||
// Get fg/bg colors
|
||||
ColorBar* colorbar = ColorBar::instance();
|
||||
params.fg = colorbar->getFgColor();
|
||||
params.bg = colorbar->getBgColor();
|
||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
||||
params.fg = app::Color::fromIndex(colorbar->getFgTile()); // TODO Color::fromTileIndex?
|
||||
params.bg = app::Color::fromIndex(colorbar->getBgTile());
|
||||
if (!params.fg.isValid() || !params.bg.isValid())
|
||||
return nullptr;
|
||||
}
|
||||
else {
|
||||
params.fg = colorbar->getFgColor();
|
||||
params.bg = colorbar->getBgColor();
|
||||
}
|
||||
if (!params.fg.isValid() ||
|
||||
!params.bg.isValid())
|
||||
return nullptr;
|
||||
@ -931,14 +966,13 @@ tools::ToolLoop* create_tool_loop_preview(
|
||||
params.brush = brush;
|
||||
params.button = tools::ToolLoop::Left;
|
||||
params.controller = params.tool->getController(params.button);
|
||||
params.gridBounds = editor->getSite().gridBounds();
|
||||
|
||||
// Create the new tool loop
|
||||
try {
|
||||
fill_toolloop_params_from_tool_preferences(params);
|
||||
|
||||
return new PreviewToolLoopImpl(
|
||||
editor, params, image, celOrigin);
|
||||
editor, site, params, image, celOrigin);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
LOG(ERROR, e.what());
|
||||
|
@ -46,8 +46,6 @@ namespace app {
|
||||
int tolerance = 0;
|
||||
bool contiguous = true;
|
||||
tools::FreehandAlgorithm freehandAlgorithm = tools::FreehandAlgorithm::DEFAULT;
|
||||
|
||||
gfx::Rect gridBounds;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -86,6 +86,8 @@ ExpandCelCanvas::ExpandCelCanvas(
|
||||
, m_closed(false)
|
||||
, m_committed(false)
|
||||
, m_cmds(cmds)
|
||||
, m_grid(site.grid())
|
||||
, m_tilemapMode(site.tilemapMode())
|
||||
, m_tilesetMode(site.tilesetMode())
|
||||
{
|
||||
if (m_layer && m_layer->isTilemap()) {
|
||||
@ -126,6 +128,10 @@ ExpandCelCanvas::ExpandCelCanvas(
|
||||
m_bounds = spriteBounds;
|
||||
}
|
||||
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
m_bounds = site.grid().canvasToTile(m_bounds);
|
||||
}
|
||||
|
||||
// We have to adjust the cel position to match the m_dstImage
|
||||
// position (the new m_dstImage will be used in RenderEngine to
|
||||
// draw this cel).
|
||||
@ -140,7 +146,8 @@ ExpandCelCanvas::ExpandCelCanvas(
|
||||
}
|
||||
// If we are in a tilemap, we use m_dstImage to draw pixels (instead
|
||||
// of the tilemap image).
|
||||
else if (m_layer->isTilemap()) {
|
||||
else if (m_layer->isTilemap() &&
|
||||
m_tilemapMode == TilemapMode::Pixels) {
|
||||
// Calling "getDestCanvas()" we create the m_dstImage
|
||||
getDestCanvas();
|
||||
m_cel->data()->setImage(m_dstImage, m_layer);
|
||||
@ -191,7 +198,8 @@ void ExpandCelCanvas::commit()
|
||||
gfx::Rect trimBounds = getTrimDstImageBounds();
|
||||
if (!trimBounds.isEmpty()) {
|
||||
// Convert the image to tiles
|
||||
if (m_layer->isTilemap()) {
|
||||
if (m_layer->isTilemap() &&
|
||||
m_tilemapMode == TilemapMode::Pixels) {
|
||||
doc::ImageRef newTilemap;
|
||||
draw_image_into_new_tilemap_cel(
|
||||
m_cmds, static_cast<doc::LayerTilemap*>(m_layer), m_cel,
|
||||
@ -226,7 +234,8 @@ void ExpandCelCanvas::commit()
|
||||
m_cel->setPosition(m_origCelPos);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (m_layer->isTilemap()) {
|
||||
if (m_layer->isTilemap() &&
|
||||
m_tilemapMode == TilemapMode::Pixels) {
|
||||
ASSERT(m_cel->image() != m_celImage.get());
|
||||
}
|
||||
else {
|
||||
@ -253,7 +262,8 @@ void ExpandCelCanvas::commit()
|
||||
EXP_TRACE(" - regionToPatch", regionToPatch->bounds());
|
||||
|
||||
// Convert the image to tiles again
|
||||
if (m_layer->isTilemap()) {
|
||||
if (m_layer->isTilemap() &&
|
||||
m_tilemapMode == TilemapMode::Pixels) {
|
||||
ASSERT(m_celImage.get() != m_cel->image());
|
||||
ASSERT(m_celImage->pixelFormat() == IMAGE_TILEMAP);
|
||||
|
||||
@ -326,7 +336,6 @@ void ExpandCelCanvas::rollback()
|
||||
}
|
||||
// Restore the original tilemap
|
||||
else if (m_layer->isTilemap()) {
|
||||
ASSERT(m_cel->image()->pixelFormat() == m_sprite->pixelFormat());
|
||||
ASSERT(m_celImage->pixelFormat() == IMAGE_TILEMAP);
|
||||
m_cel->data()->setImage(m_celImage,
|
||||
m_cel->layer());
|
||||
@ -340,8 +349,10 @@ Image* ExpandCelCanvas::getSourceCanvas()
|
||||
ASSERT((m_flags & NeedsSource) == NeedsSource);
|
||||
|
||||
if (!m_srcImage) {
|
||||
m_srcImage.reset(Image::create(m_sprite->pixelFormat(),
|
||||
m_bounds.w, m_bounds.h, src_buffer));
|
||||
m_srcImage.reset(
|
||||
Image::create(m_tilemapMode == TilemapMode::Tiles ? IMAGE_TILEMAP:
|
||||
m_sprite->pixelFormat(),
|
||||
m_bounds.w, m_bounds.h, src_buffer));
|
||||
|
||||
m_srcImage->setMaskColor(m_sprite->transparentColor());
|
||||
}
|
||||
@ -351,8 +362,10 @@ Image* ExpandCelCanvas::getSourceCanvas()
|
||||
Image* ExpandCelCanvas::getDestCanvas()
|
||||
{
|
||||
if (!m_dstImage) {
|
||||
m_dstImage.reset(Image::create(m_sprite->pixelFormat(),
|
||||
m_bounds.w, m_bounds.h, dst_buffer));
|
||||
m_dstImage.reset(
|
||||
Image::create(m_tilemapMode == TilemapMode::Tiles ? IMAGE_TILEMAP:
|
||||
m_sprite->pixelFormat(),
|
||||
m_bounds.w, m_bounds.h, dst_buffer));
|
||||
|
||||
m_dstImage->setMaskColor(m_sprite->transparentColor());
|
||||
}
|
||||
@ -365,7 +378,16 @@ void ExpandCelCanvas::validateSourceCanvas(const gfx::Region& rgn)
|
||||
|
||||
getSourceCanvas();
|
||||
|
||||
gfx::Region rgnToValidate(rgn);
|
||||
gfx::Region rgnToValidate;
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
for (const auto& rc : rgn)
|
||||
rgnToValidate |= gfx::Region(m_grid.canvasToTile(rc));
|
||||
}
|
||||
else {
|
||||
rgnToValidate = rgn;
|
||||
}
|
||||
EXP_TRACE(" ->", rgnToValidate.bounds());
|
||||
|
||||
rgnToValidate.offset(-m_bounds.origin());
|
||||
rgnToValidate.createSubtraction(rgnToValidate, m_validSrcRegion);
|
||||
rgnToValidate.createIntersection(rgnToValidate, gfx::Region(m_srcImage->bounds()));
|
||||
@ -380,7 +402,10 @@ void ExpandCelCanvas::validateSourceCanvas(const gfx::Region& rgn)
|
||||
for (const auto& rc : rgnToClear)
|
||||
fill_rect(m_srcImage.get(), rc, m_srcImage->maskColor());
|
||||
|
||||
if (m_celImage->pixelFormat() == IMAGE_TILEMAP) {
|
||||
if (m_celImage->pixelFormat() == IMAGE_TILEMAP &&
|
||||
m_srcImage->pixelFormat() != IMAGE_TILEMAP) {
|
||||
ASSERT(m_tilemapMode == TilemapMode::Pixels);
|
||||
|
||||
// For tilemaps, we can use the Render class to render visible
|
||||
// tiles in the rgnToValidate of this cel.
|
||||
render::Render subRender;
|
||||
@ -399,6 +424,9 @@ void ExpandCelCanvas::validateSourceCanvas(const gfx::Region& rgn)
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(m_celImage->pixelFormat() != IMAGE_TILEMAP ||
|
||||
m_tilemapMode == TilemapMode::Tiles);
|
||||
|
||||
// We can copy the cel image directly
|
||||
for (const auto& rc : rgnToValidate)
|
||||
m_srcImage->copy(
|
||||
@ -436,7 +464,16 @@ void ExpandCelCanvas::validateDestCanvas(const gfx::Region& rgn)
|
||||
|
||||
getDestCanvas(); // Create m_dstImage
|
||||
|
||||
gfx::Region rgnToValidate(rgn);
|
||||
gfx::Region rgnToValidate;
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
for (const auto& rc : rgn)
|
||||
rgnToValidate |= gfx::Region(m_grid.canvasToTile(rc));
|
||||
}
|
||||
else {
|
||||
rgnToValidate = rgn;
|
||||
}
|
||||
EXP_TRACE(" ->", rgnToValidate.bounds());
|
||||
|
||||
rgnToValidate.offset(-m_bounds.origin());
|
||||
rgnToValidate.createSubtraction(rgnToValidate, m_validDstRegion);
|
||||
rgnToValidate.createIntersection(rgnToValidate, gfx::Region(m_dstImage->bounds()));
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -9,8 +9,10 @@
|
||||
#define APP_UTIL_EXPAND_CEL_CANVAS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/tilemap_mode.h"
|
||||
#include "app/tileset_mode.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/grid.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "gfx/point.h"
|
||||
@ -100,6 +102,8 @@ namespace app {
|
||||
// reduce the patched region because both images will be the same.
|
||||
bool m_canCompareSrcVsDst;
|
||||
|
||||
doc::Grid m_grid;
|
||||
TilemapMode m_tilemapMode;
|
||||
TilesetMode m_tilesetMode;
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -399,7 +399,7 @@ bool shrink_bounds2(const Image* a,
|
||||
case IMAGE_GRAYSCALE: return shrink_bounds_templ2<GrayscaleTraits>(a, b, bounds);
|
||||
case IMAGE_INDEXED: return shrink_bounds_templ2<IndexedTraits>(a, b, bounds);
|
||||
case IMAGE_BITMAP: return shrink_bounds_templ2<BitmapTraits>(a, b, bounds);
|
||||
// case IMAGE_TILEMAP: return shrink_bounds_templ2<TilemapTraits>(a, b, bounds);
|
||||
case IMAGE_TILEMAP: return shrink_bounds_templ2<TilemapTraits>(a, b, bounds);
|
||||
}
|
||||
ASSERT(false);
|
||||
return false;
|
||||
|
@ -677,7 +677,8 @@ void Render::renderLayer(
|
||||
|
||||
CompositeImageFunc compositeImage =
|
||||
getImageComposition(
|
||||
dstImage->pixelFormat(),
|
||||
(dstImage->pixelFormat() != IMAGE_TILEMAP ? dstImage->pixelFormat():
|
||||
m_sprite->pixelFormat()),
|
||||
m_sprite->pixelFormat(), layer);
|
||||
if (!compositeImage)
|
||||
return;
|
||||
@ -757,7 +758,10 @@ void Render::renderSprite(
|
||||
// Overlay preview image
|
||||
if (m_previewImage &&
|
||||
m_selectedLayer == nullptr &&
|
||||
m_selectedFrame == frame) {
|
||||
m_selectedFrame == frame
|
||||
// TODO allow previewImage for tilemaps?
|
||||
&& m_previewImage->pixelFormat() == m_sprite->pixelFormat()
|
||||
) {
|
||||
renderImage(
|
||||
dstImage,
|
||||
m_previewImage,
|
||||
@ -768,7 +772,8 @@ void Render::renderSprite(
|
||||
area,
|
||||
getImageComposition(
|
||||
dstImage->pixelFormat(),
|
||||
m_previewImage->pixelFormat(), sprite->root()),
|
||||
m_previewImage->pixelFormat(),
|
||||
sprite->root()),
|
||||
255,
|
||||
m_previewBlendMode);
|
||||
}
|
||||
@ -1033,11 +1038,7 @@ void Render::renderLayer(
|
||||
}
|
||||
|
||||
if (drawExtra) {
|
||||
extraArea = gfx::Rect(
|
||||
m_extraCel->x(),
|
||||
m_extraCel->y(),
|
||||
m_extraImage->width(),
|
||||
m_extraImage->height());
|
||||
extraArea = m_extraCel->bounds();
|
||||
extraArea = m_proj.apply(extraArea);
|
||||
if (m_proj.scaleX() < 1.0) extraArea.w--;
|
||||
if (m_proj.scaleY() < 1.0) extraArea.h--;
|
||||
@ -1178,14 +1179,15 @@ void Render::renderLayer(
|
||||
if (drawExtra && m_extraType != ExtraType::NONE) {
|
||||
if (m_extraCel->opacity() > 0) {
|
||||
renderCel(
|
||||
image, m_extraImage,
|
||||
nullptr, // Without layer
|
||||
image,
|
||||
m_sprite,
|
||||
m_extraImage,
|
||||
m_currentLayer, // Current layer (useful to use get the tileset if extra cel is a tilemap)
|
||||
m_sprite->palette(frame),
|
||||
m_extraCel->bounds(),
|
||||
gfx::Clip(area.dst.x+extraArea.x-area.src.x,
|
||||
area.dst.y+extraArea.y-area.src.y,
|
||||
extraArea),
|
||||
compositeImage,
|
||||
m_extraCel->opacity(),
|
||||
m_extraBlendMode);
|
||||
}
|
||||
@ -1285,12 +1287,17 @@ void Render::renderCel(
|
||||
const tile_t t = cel_image->getPixel(u, v);
|
||||
const tile_index i = tile_geti(t);
|
||||
|
||||
const ImageRef tile_image = tileset->get(i);
|
||||
if (!tile_image)
|
||||
continue;
|
||||
if (dst_image->pixelFormat() == IMAGE_TILEMAP) {
|
||||
put_pixel(dst_image, u-area.dst.x, v-area.dst.y, t);
|
||||
}
|
||||
else {
|
||||
const ImageRef tile_image = tileset->get(i);
|
||||
if (!tile_image)
|
||||
continue;
|
||||
|
||||
renderImage(dst_image, tile_image.get(), pal, tileBoundsOnCanvas,
|
||||
area, compositeImage, opacity, blendMode);
|
||||
renderImage(dst_image, tile_image.get(), pal, tileBoundsOnCanvas,
|
||||
area, compositeImage, opacity, blendMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1374,8 +1381,16 @@ CompositeImageFunc Render::getImageComposition(
|
||||
case IMAGE_INDEXED: return get_fastest_composition_path<IndexedTraits, IndexedTraits>(m_proj, finegrain);
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_TILEMAP:
|
||||
switch (dstFormat) {
|
||||
case IMAGE_TILEMAP:
|
||||
return get_fastest_composition_path<TilemapTraits, TilemapTraits>(m_proj, finegrain);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE_RENDER_CEL("Render::getImageComposition srcFormat", srcFormat, "dstFormat", dstFormat);
|
||||
ASSERT(false && "Invalid pixel formats");
|
||||
return nullptr;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user