mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-22 06:41:08 +00:00
Merge branch 'fix-tile-mode' into tilemap-editor
This commit is contained in:
commit
24a2d9527b
@ -1,6 +1,6 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2016 David Capello
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/layer_tilemap.h"
|
||||
#include "doc/primitives.h"
|
||||
|
||||
namespace app {
|
||||
@ -24,9 +25,7 @@ CropCel::CropCel(Cel* cel, const gfx::Rect& newBounds)
|
||||
: WithCel(cel)
|
||||
, m_oldOrigin(cel->position())
|
||||
, m_newOrigin(newBounds.origin())
|
||||
// Instead of using cel->bounds() we use the image size because it
|
||||
// works for tilemaps too.
|
||||
, m_oldBounds(cel->position(), cel->image()->size())
|
||||
, m_oldBounds(cel->bounds())
|
||||
, m_newBounds(newBounds)
|
||||
{
|
||||
m_oldBounds.offset(-m_newOrigin);
|
||||
@ -51,10 +50,18 @@ void CropCel::cropImage(const gfx::Point& origin,
|
||||
{
|
||||
Cel* cel = this->cel();
|
||||
|
||||
gfx::Rect localBounds(bounds);
|
||||
if (cel->layer()->isTilemap()) {
|
||||
doc::Tileset* tileset = static_cast<LayerTilemap*>(cel->layer())->tileset();
|
||||
if (tileset) {
|
||||
doc::Grid grid = tileset->grid();
|
||||
localBounds = grid.canvasToTile(bounds);
|
||||
}
|
||||
}
|
||||
if (bounds != cel->image()->bounds()) {
|
||||
ImageRef image(crop_image(cel->image(),
|
||||
bounds.x, bounds.y,
|
||||
bounds.w, bounds.h,
|
||||
localBounds.x, localBounds.y,
|
||||
localBounds.w, localBounds.h,
|
||||
cel->image()->maskColor()));
|
||||
ObjectId id = cel->image()->id();
|
||||
ObjectVersion ver = cel->image()->version();
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -14,6 +15,7 @@
|
||||
#include "app/cmd/crop_cel.h"
|
||||
#include "app/cmd/trim_cel.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/layer_tilemap.h"
|
||||
|
||||
namespace app {
|
||||
namespace cmd {
|
||||
@ -36,17 +38,37 @@ void PatchCel::onExecute()
|
||||
{
|
||||
Cel* cel = this->cel();
|
||||
|
||||
const gfx::Rect newBounds =
|
||||
cel->bounds() | gfx::Rect(m_region.bounds()).offset(m_pos);
|
||||
if (cel->bounds() != newBounds) {
|
||||
executeAndAdd(new CropCel(cel, newBounds));
|
||||
gfx::Rect newBounds;
|
||||
gfx::Region regionInTiles;
|
||||
doc::Grid grid;
|
||||
if (cel->image()->pixelFormat() == IMAGE_TILEMAP) {
|
||||
newBounds = cel->bounds() | m_region.bounds();
|
||||
auto tileset = static_cast<LayerTilemap*>(cel->layer())->tileset();
|
||||
grid = tileset->grid();
|
||||
grid.origin(m_pos);
|
||||
regionInTiles = grid.canvasToTile(m_region);
|
||||
}
|
||||
else {
|
||||
newBounds = cel->bounds() | gfx::Rect(m_region.bounds()).offset(m_pos);
|
||||
}
|
||||
|
||||
executeAndAdd(
|
||||
new CopyRegion(cel->image(),
|
||||
m_patch,
|
||||
m_region,
|
||||
m_pos - cel->position()));
|
||||
if (cel->bounds() != newBounds)
|
||||
executeAndAdd(new CropCel(cel, newBounds));
|
||||
|
||||
if (cel->image()->pixelFormat() == IMAGE_TILEMAP) {
|
||||
executeAndAdd(
|
||||
new CopyRegion(cel->image(),
|
||||
m_patch,
|
||||
regionInTiles,
|
||||
-grid.canvasToTile(cel->position())));
|
||||
}
|
||||
else {
|
||||
executeAndAdd(
|
||||
new CopyRegion(cel->image(),
|
||||
m_patch,
|
||||
m_region,
|
||||
m_pos - cel->position()));
|
||||
}
|
||||
|
||||
executeAndAdd(new TrimCel(cel));
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/tile.h"
|
||||
#include "gfx/hsl.h"
|
||||
#include "gfx/hsv.h"
|
||||
#include "gfx/rgb.h"
|
||||
@ -83,7 +84,7 @@ Color Color::fromGray(int g, int a)
|
||||
// static
|
||||
Color Color::fromIndex(int index)
|
||||
{
|
||||
ASSERT(index >= 0);
|
||||
ASSERT(index >= 0 || index == tile_i_notile);
|
||||
|
||||
Color color(Color::IndexType);
|
||||
color.m_value.index = index;
|
||||
@ -114,6 +115,7 @@ Color Color::fromImage(PixelFormat pixelFormat, color_t c)
|
||||
break;
|
||||
|
||||
case IMAGE_INDEXED:
|
||||
case IMAGE_TILEMAP:
|
||||
color = Color::fromIndex(c);
|
||||
break;
|
||||
}
|
||||
|
@ -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
|
||||
@ -270,7 +270,8 @@ bool DocApi::cropCel(LayerImage* layer,
|
||||
crop_image(image,
|
||||
paintPos.x, paintPos.y,
|
||||
newCelBounds.w, newCelBounds.h,
|
||||
m_document->bgColor(layer)));
|
||||
image->pixelFormat() == IMAGE_TILEMAP ?
|
||||
tile_i_notile : m_document->bgColor(layer)));
|
||||
|
||||
// Try to shrink the image ignoring transparent borders
|
||||
gfx::Rect frameBounds;
|
||||
@ -283,7 +284,8 @@ bool DocApi::cropCel(LayerImage* layer,
|
||||
crop_image(newImage.get(),
|
||||
frameBounds.x, frameBounds.y,
|
||||
frameBounds.w, frameBounds.h,
|
||||
m_document->bgColor(layer)));
|
||||
image->pixelFormat() == IMAGE_TILEMAP ?
|
||||
tile_i_notile : m_document->bgColor(layer)));
|
||||
|
||||
newCelPos += frameBounds.origin();
|
||||
}
|
||||
|
@ -135,11 +135,22 @@ app::Color Color_new(lua_State* L, int index)
|
||||
}
|
||||
else
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Convert { index } into a Color
|
||||
if (lua_getfield(L, index, "index") != LUA_TNIL) {
|
||||
color = app::Color::fromIndex(lua_tonumber(L, -1));
|
||||
lua_pop(L, 1);
|
||||
return color;
|
||||
}
|
||||
else
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
// raw color into app color
|
||||
else if (!lua_isnone(L, index)) {
|
||||
if (lua_isinteger(L, index) && (index < 0 || lua_isnone(L, index+1))) {
|
||||
doc::color_t docColor = lua_tointeger(L, index);
|
||||
|
||||
// TODO depending on current pixel format?
|
||||
switch (app_get_current_pixel_format()) {
|
||||
case IMAGE_RGB:
|
||||
color = app::Color::fromRgb(doc::rgba_getr(docColor),
|
||||
|
@ -145,7 +145,7 @@ public:
|
||||
}
|
||||
|
||||
void processPixel(int x, int y) {
|
||||
*SimpleInkProcessing<CopyInkProcessing<ImageTraits>, ImageTraits>::m_dstAddress = m_color;
|
||||
*this->m_dstAddress = m_color;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -96,7 +96,13 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
if (loop->getBrush()->type() == doc::kImageBrushType) {
|
||||
// TODO support different ink types for tilemaps (even custom brushes,
|
||||
// and custom inks script-driven)
|
||||
if (loop->getDstImage()->pixelFormat() == IMAGE_TILEMAP) {
|
||||
setProc(new CopyInkProcessing<TilemapTraits>(loop));
|
||||
}
|
||||
// Custom brushes
|
||||
else if (loop->getBrush()->type() == doc::kImageBrushType) {
|
||||
switch (m_type) {
|
||||
case Simple:
|
||||
setProc(get_ink_proc<BrushSimpleInkProcessing>(loop));
|
||||
@ -158,12 +164,7 @@ public:
|
||||
break;
|
||||
}
|
||||
case Copy:
|
||||
if (loop->getDstImage()->pixelFormat() == IMAGE_TILEMAP) {
|
||||
setProc(new CopyInkProcessing<TilemapTraits>(loop));
|
||||
}
|
||||
else {
|
||||
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||
}
|
||||
setProc(get_ink_proc<CopyInkProcessing>(loop));
|
||||
break;
|
||||
case LockAlpha:
|
||||
setProc(get_ink_proc<LockAlphaInkProcessing>(loop));
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "app/tools/ink.h"
|
||||
#include "app/tools/tool_loop.h"
|
||||
#include "app/util/wrap_value.h"
|
||||
#include "base/clamp.h"
|
||||
#include "doc/brush.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/sprite.h"
|
||||
@ -24,14 +25,19 @@ namespace tools {
|
||||
using namespace doc;
|
||||
using namespace filters;
|
||||
|
||||
void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop)
|
||||
void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop,
|
||||
bool adjustCoordinates)
|
||||
{
|
||||
Ink* ink = loop->getInk();
|
||||
TiledMode tiledMode = loop->getTiledMode();
|
||||
const int dstw = loop->getDstImage()->width();
|
||||
const int dsth = loop->getDstImage()->height();
|
||||
int x, w, size; // width or height
|
||||
|
||||
// In case the ink needs original cel coordinates, we have to
|
||||
// translate the x1/y/x2 coordinate.
|
||||
if (loop->getInk()->needsCelCoordinates()) {
|
||||
if (adjustCoordinates &&
|
||||
ink->needsCelCoordinates()) {
|
||||
gfx::Point origin = loop->getCelOrigin();
|
||||
x1 -= origin.x;
|
||||
x2 -= origin.x;
|
||||
@ -40,52 +46,49 @@ void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop)
|
||||
|
||||
// Tiled in Y axis
|
||||
if (int(tiledMode) & int(TiledMode::Y_AXIS)) {
|
||||
size = loop->getDstImage()->height(); // size = image height
|
||||
size = dsth; // size = image height
|
||||
y = wrap_value(y, size);
|
||||
}
|
||||
else if (y < 0 || y >= loop->getDstImage()->height())
|
||||
else if (y < 0 || y >= dsth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Tiled in X axis
|
||||
if (int(tiledMode) & int(TiledMode::X_AXIS)) {
|
||||
if (x1 > x2)
|
||||
return;
|
||||
|
||||
size = loop->getDstImage()->width(); // size = image width
|
||||
size = dstw; // size = image width
|
||||
w = x2-x1+1;
|
||||
if (w >= size)
|
||||
loop->getInk()->inkHline(0, y, size-1, loop);
|
||||
ink->inkHline(0, y, size-1, loop);
|
||||
else {
|
||||
x = wrap_value(x1, loop->sprite()->width());
|
||||
if (x+w <= loop->sprite()->width()) {
|
||||
// Here we asure that tile limit line does not bisect the current
|
||||
// scanline, i.e. the scanline is enterely contained inside the tile.
|
||||
loop->getInk()->prepareUForPointShapeWholeScanline(loop, x1);
|
||||
loop->getInk()->inkHline(x, y, x+w-1, loop);
|
||||
ink->prepareUForPointShapeWholeScanline(loop, x1);
|
||||
ink->inkHline(x, y, x+w-1, loop);
|
||||
}
|
||||
else {
|
||||
// Here the tile limit line bisect the current scanline.
|
||||
// So we need to execute TWO times the inkHline function, each one with a different m_u.
|
||||
loop->getInk()->prepareUForPointShapeSlicedScanline(loop, true, x1);// true = left slice
|
||||
loop->getInk()->inkHline(x, y, size-1, loop);
|
||||
ink->prepareUForPointShapeSlicedScanline(loop, true, x1);// true = left slice
|
||||
ink->inkHline(x, y, size-1, loop);
|
||||
|
||||
loop->getInk()->prepareUForPointShapeSlicedScanline(loop, false, x1);// false = right slice
|
||||
loop->getInk()->inkHline(0, y, w-(size-x)-1, loop);
|
||||
ink->prepareUForPointShapeSlicedScanline(loop, false, x1);// false = right slice
|
||||
ink->inkHline(0, y, w-(size-x)-1, loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clipped in X axis
|
||||
else {
|
||||
if (x1 < 0)
|
||||
x1 = 0;
|
||||
|
||||
if (x2 >= loop->getDstImage()->width())
|
||||
x2 = loop->getDstImage()->width()-1;
|
||||
|
||||
x1 = base::clamp(x1, 0, dstw-1);
|
||||
x2 = base::clamp(x2, 0, dstw-1);
|
||||
if (x2-x1+1 < 1)
|
||||
return;
|
||||
|
||||
loop->getInk()->inkHline(x1, y, x2, loop);
|
||||
ink->inkHline(x1, y, x2, loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,8 @@ namespace app {
|
||||
protected:
|
||||
// Calls loop->getInk()->inkHline() function for each horizontal-scanline
|
||||
// that should be drawn (applying the "tiled" mode loop->getTiledMode())
|
||||
static void doInkHline(int x1, int y, int x2, ToolLoop* loop);
|
||||
static void doInkHline(int x1, int y, int x2, ToolLoop* loop,
|
||||
const bool adjustCoordinates = true);
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
|
@ -48,7 +48,11 @@ public:
|
||||
gfx::Point newPos = grid.canvasToTile(pt.toPoint());
|
||||
|
||||
loop->getInk()->prepareForPointShape(loop, true, newPos.x, newPos.y);
|
||||
doInkHline(newPos.x, newPos.y, newPos.x, loop);
|
||||
doInkHline(
|
||||
newPos.x, newPos.y, newPos.x, loop,
|
||||
// Don't adjust by loop->getCelOrigin() because loop->getGrid()
|
||||
// is already adjusted to the new cel position.
|
||||
false);
|
||||
}
|
||||
|
||||
void getModifiedArea(ToolLoop* loop, int x, int y, Rect& area) override {
|
||||
|
@ -5,6 +5,8 @@
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#define BP_TRACE(...) // TRACEARGS(__VA_ARGS__)
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
@ -28,6 +30,7 @@
|
||||
#include "app/ui/editor/tool_loop_impl.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/wrap_value.h"
|
||||
#include "base/debug.h"
|
||||
#include "doc/algo.h"
|
||||
#include "doc/blend_internals.h"
|
||||
#include "doc/brush.h"
|
||||
@ -35,6 +38,7 @@
|
||||
#include "doc/image_impl.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "gfx/rect_io.h"
|
||||
#include "os/display.h"
|
||||
#include "render/render.h"
|
||||
#include "ui/manager.h"
|
||||
@ -230,38 +234,44 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
brush->bounds());
|
||||
gfx::Rect brushBounds = origBrushBounds;
|
||||
brushBounds.offset(spritePos);
|
||||
gfx::Rect extraCelBounds = brushBounds;
|
||||
gfx::Rect extraCelBoundsInCanvas = brushBounds;
|
||||
|
||||
// Tiled mode might require a bigger extra cel (to show the tiled)
|
||||
if (int(m_editor->docPref().tiled.mode()) & int(filters::TiledMode::X_AXIS)) {
|
||||
brushBounds.x = wrap_value(brushBounds.x, sprite->width());
|
||||
extraCelBounds.x = brushBounds.x;
|
||||
if ((extraCelBounds.x < 0 && extraCelBounds.x2() > 0) ||
|
||||
(extraCelBounds.x < sprite->width() && extraCelBounds.x2() > sprite->width())) {
|
||||
extraCelBounds.x = 0;
|
||||
extraCelBounds.w = sprite->width();
|
||||
extraCelBoundsInCanvas.x = brushBounds.x;
|
||||
if ((extraCelBoundsInCanvas.x < 0 && extraCelBoundsInCanvas.x2() > 0) ||
|
||||
(extraCelBoundsInCanvas.x < sprite->width() && extraCelBoundsInCanvas.x2() > sprite->width())) {
|
||||
extraCelBoundsInCanvas.x = 0;
|
||||
extraCelBoundsInCanvas.w = sprite->width();
|
||||
}
|
||||
}
|
||||
if (int(m_editor->docPref().tiled.mode()) & int(filters::TiledMode::Y_AXIS)) {
|
||||
brushBounds.y = wrap_value(brushBounds.y, sprite->height());
|
||||
extraCelBounds.y = brushBounds.y;
|
||||
if ((extraCelBounds.y < 0 && extraCelBounds.y2() > 0) ||
|
||||
(extraCelBounds.y < sprite->height() && extraCelBounds.y2() > sprite->height())) {
|
||||
extraCelBounds.y = 0;
|
||||
extraCelBounds.h = sprite->height();
|
||||
extraCelBoundsInCanvas.y = brushBounds.y;
|
||||
if ((extraCelBoundsInCanvas.y < 0 && extraCelBoundsInCanvas.y2() > 0) ||
|
||||
(extraCelBoundsInCanvas.y < sprite->height() && extraCelBoundsInCanvas.y2() > sprite->height())) {
|
||||
extraCelBoundsInCanvas.y = 0;
|
||||
extraCelBoundsInCanvas.h = sprite->height();
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Rect extraCelBoundsInCanvas;
|
||||
gfx::Rect extraCelBounds;
|
||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
||||
ASSERT(layer->isTilemap());
|
||||
extraCelBounds.setOrigin(site.grid().canvasToTile(extraCelBounds.origin()));
|
||||
extraCelBoundsInCanvas = site.grid().tileToCanvas(extraCelBounds);
|
||||
doc::Grid grid = site.grid();
|
||||
extraCelBounds = grid.canvasToTile(extraCelBoundsInCanvas);
|
||||
extraCelBoundsInCanvas = grid.tileToCanvas(extraCelBounds);
|
||||
}
|
||||
else {
|
||||
extraCelBoundsInCanvas = extraCelBounds;
|
||||
extraCelBounds = extraCelBoundsInCanvas;
|
||||
}
|
||||
|
||||
BP_TRACE("BrushPreview:",
|
||||
"brushBounds", brushBounds,
|
||||
"extraCelBounds", extraCelBounds,
|
||||
"extraCelBoundsInCanvas", extraCelBoundsInCanvas);
|
||||
|
||||
// Create the extra cel to show the brush preview
|
||||
Cel* cel = site.cel();
|
||||
|
||||
@ -287,9 +297,15 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
document->setExtraCel(m_extraCel);
|
||||
|
||||
Image* extraImage = m_extraCel->image();
|
||||
extraImage->setMaskColor(mask_index);
|
||||
clear_image(extraImage,
|
||||
(extraImage->pixelFormat() == IMAGE_INDEXED ? mask_index: 0));
|
||||
if (extraImage->pixelFormat() == IMAGE_TILEMAP) {
|
||||
extraImage->setMaskColor(tile_i_notile);
|
||||
clear_image(extraImage, tile_i_notile);
|
||||
}
|
||||
else {
|
||||
extraImage->setMaskColor(mask_index);
|
||||
clear_image(extraImage,
|
||||
(extraImage->pixelFormat() == IMAGE_INDEXED ? mask_index: 0));
|
||||
}
|
||||
|
||||
if (layer) {
|
||||
render::Render().renderLayer(
|
||||
|
@ -124,7 +124,7 @@ protected:
|
||||
|
||||
public:
|
||||
ToolLoopBase(Editor* editor,
|
||||
Site& site, const doc::Grid& grid,
|
||||
Site& site,
|
||||
ToolLoopParams& params)
|
||||
: m_editor(editor)
|
||||
, m_tool(params.tool)
|
||||
@ -143,8 +143,8 @@ public:
|
||||
, m_contiguous(params.contiguous)
|
||||
, m_snapToGrid(m_docPref.grid.snap())
|
||||
, m_isSelectingTiles(false)
|
||||
, m_grid(grid)
|
||||
, m_gridBounds(grid.origin(), grid.tileSize())
|
||||
, m_grid(site.grid())
|
||||
, m_gridBounds(m_grid.origin(), m_grid.tileSize())
|
||||
, m_button(params.button)
|
||||
, m_ink(params.ink->clone())
|
||||
, m_controller(params.controller)
|
||||
@ -454,11 +454,10 @@ class ToolLoopImpl : public ToolLoopBase {
|
||||
public:
|
||||
ToolLoopImpl(Editor* editor,
|
||||
Site& site,
|
||||
const doc::Grid& grid,
|
||||
Context* context,
|
||||
ToolLoopParams& params,
|
||||
const bool saveLastPoint)
|
||||
: ToolLoopBase(editor, site, grid, params)
|
||||
: ToolLoopBase(editor, site, params)
|
||||
, m_context(context)
|
||||
, m_canceled(false)
|
||||
, m_tx(m_context,
|
||||
@ -549,6 +548,10 @@ public:
|
||||
m_maskOrigin = (!m_mask->isEmpty() ? gfx::Point(m_mask->bounds().x-m_celOrigin.x,
|
||||
m_mask->bounds().y-m_celOrigin.y):
|
||||
gfx::Point(0, 0));
|
||||
|
||||
// Setup the new grid of ExpandCelCanvas which can be displaced to
|
||||
// match the new temporal cel position (m_celOrigin).
|
||||
m_grid = m_expandCelCanvas->getGrid();
|
||||
}
|
||||
|
||||
~ToolLoopImpl() {
|
||||
@ -714,7 +717,6 @@ tools::ToolLoop* create_tool_loop(
|
||||
const bool selectTiles)
|
||||
{
|
||||
Site site = editor->getSite();
|
||||
doc::Grid grid = site.grid();
|
||||
|
||||
ToolLoopParams params;
|
||||
params.tool = editor->getCurrentEditorTool();
|
||||
@ -820,7 +822,7 @@ tools::ToolLoop* create_tool_loop(
|
||||
|
||||
ASSERT(context->activeDocument() == editor->document());
|
||||
auto toolLoop = new ToolLoopImpl(
|
||||
editor, site, grid, context, params, saveLastPoint);
|
||||
editor, site, context, params, saveLastPoint);
|
||||
|
||||
if (selectTiles)
|
||||
toolLoop->forceSnapToTiles();
|
||||
@ -859,8 +861,7 @@ tools::ToolLoop* create_tool_loop_for_script(
|
||||
|
||||
Site site2(site);
|
||||
return new ToolLoopImpl(
|
||||
nullptr, site2, site2.grid(),
|
||||
context, params, false);
|
||||
nullptr, site2, context, params, false);
|
||||
}
|
||||
catch (const std::exception& ex) {
|
||||
Console::showException(ex);
|
||||
@ -885,7 +886,7 @@ public:
|
||||
ToolLoopParams& params,
|
||||
Image* image,
|
||||
const gfx::Point& celOrigin)
|
||||
: ToolLoopBase(editor, site, site.grid(), params)
|
||||
: ToolLoopBase(editor, site, params)
|
||||
, m_image(image)
|
||||
{
|
||||
m_celOrigin = celOrigin;
|
||||
|
@ -351,7 +351,8 @@ void draw_image_into_new_tilemap_cel(
|
||||
newTilemap.reset(doc::Image::create(IMAGE_TILEMAP,
|
||||
tilemapBounds.w,
|
||||
tilemapBounds.h));
|
||||
newTilemap->clear(0); // <- This should not necessary
|
||||
newTilemap->setMaskColor(tile_i_notile);
|
||||
newTilemap->clear(tile_i_notile);
|
||||
}
|
||||
else {
|
||||
ASSERT(tilemapBounds.w == newTilemap->width());
|
||||
@ -444,7 +445,8 @@ void modify_tilemap_cel_region(
|
||||
newTilemapBounds.w,
|
||||
newTilemapBounds.h));
|
||||
|
||||
newTilemap->clear(0); // TODO find the tile with empty content?
|
||||
newTilemap->setMaskColor(tile_i_notile);
|
||||
newTilemap->clear(tile_i_notile); // TODO find the tile with empty content?
|
||||
newTilemap->copy(
|
||||
cel->image(),
|
||||
gfx::Clip(oldTilemapBounds.x-newTilemapBounds.x,
|
||||
@ -471,7 +473,7 @@ void modify_tilemap_cel_region(
|
||||
const doc::tile_index ti = doc::tile_geti(t);
|
||||
const doc::ImageRef existenTileImage = tileset->get(ti);
|
||||
|
||||
if (tilesetMode == TilesetMode::Auto)
|
||||
if (tilesetMode == TilesetMode::Auto && t != tile_i_notile)
|
||||
modifiedTileIndexes[ti] = true;
|
||||
|
||||
const gfx::Rect tileInCanvasRc(grid.tileToCanvas(tilePt), tileSize);
|
||||
@ -540,38 +542,40 @@ void modify_tilemap_cel_region(
|
||||
continue;
|
||||
|
||||
const doc::tile_t t = cel->image()->getPixel(tilePt.x, tilePt.y);
|
||||
const doc::tile_index ti = doc::tile_geti(t);
|
||||
const doc::ImageRef existenTileImage = tileset->get(ti);
|
||||
if (t != tile_i_notile) {
|
||||
const doc::tile_index ti = doc::tile_geti(t);
|
||||
const doc::ImageRef existenTileImage = tileset->get(ti);
|
||||
|
||||
const gfx::Rect tileInCanvasRc(grid.tileToCanvas(tilePt), tileSize);
|
||||
ImageRef tileImage(getTileImage(existenTileImage, tileInCanvasRc));
|
||||
if (grid.hasMask())
|
||||
mask_image(tileImage.get(), grid.mask().get());
|
||||
const gfx::Rect tileInCanvasRc(grid.tileToCanvas(tilePt), tileSize);
|
||||
ImageRef tileImage(getTileImage(existenTileImage, tileInCanvasRc));
|
||||
if (grid.hasMask())
|
||||
mask_image(tileImage.get(), grid.mask().get());
|
||||
|
||||
gfx::Region tileRgn(tileInCanvasRc);
|
||||
tileRgn.createIntersection(tileRgn, region);
|
||||
tileRgn.offset(-tileInCanvasRc.origin());
|
||||
gfx::Region tileRgn(tileInCanvasRc);
|
||||
tileRgn.createIntersection(tileRgn, region);
|
||||
tileRgn.offset(-tileInCanvasRc.origin());
|
||||
|
||||
ImageRef tileOrigImage = tileset->get(ti);
|
||||
ImageRef tileOrigImage = tileset->get(ti);
|
||||
|
||||
gfx::Region diffRgn;
|
||||
create_region_with_differences(tileOrigImage.get(),
|
||||
tileImage.get(),
|
||||
tileRgn.bounds(),
|
||||
diffRgn);
|
||||
gfx::Region diffRgn;
|
||||
create_region_with_differences(tileOrigImage.get(),
|
||||
tileImage.get(),
|
||||
tileRgn.bounds(),
|
||||
diffRgn);
|
||||
|
||||
// Keep only the modified region for this specific modification
|
||||
tileRgn &= diffRgn;
|
||||
// Keep only the modified region for this specific modification
|
||||
tileRgn &= diffRgn;
|
||||
|
||||
if (!tileRgn.isEmpty()) {
|
||||
Mod mod;
|
||||
mod.tileIndex = ti;
|
||||
mod.tileOrigImage = tileOrigImage;
|
||||
mod.tileImage = tileImage;
|
||||
mod.tileRgn = tileRgn;
|
||||
mods.push_back(mod);
|
||||
if (!tileRgn.isEmpty()) {
|
||||
Mod mod;
|
||||
mod.tileIndex = ti;
|
||||
mod.tileOrigImage = tileOrigImage;
|
||||
mod.tileImage = tileImage;
|
||||
mod.tileRgn = tileRgn;
|
||||
mods.push_back(mod);
|
||||
|
||||
modifiedTileIndexes[ti] = true;
|
||||
modifiedTileIndexes[ti] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -655,12 +659,14 @@ void remove_unused_tiles_from_tileset(
|
||||
for_each_pixel<TilemapTraits>(
|
||||
tilemapImage,
|
||||
[&unusedTiles, &n](const doc::tile_t t) {
|
||||
const doc::tile_index ti = doc::tile_geti(t);
|
||||
n = std::max<int>(n, ti+1);
|
||||
if (ti >= 0 &&
|
||||
ti < int(unusedTiles.size()) &&
|
||||
unusedTiles[ti]) {
|
||||
unusedTiles[ti] = false;
|
||||
if (t != tile_i_notile) {
|
||||
const doc::tile_index ti = doc::tile_geti(t);
|
||||
n = std::max<int>(n, ti+1);
|
||||
if (ti >= 0 &&
|
||||
ti < int(unusedTiles.size()) &&
|
||||
unusedTiles[ti]) {
|
||||
unusedTiles[ti] = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#define EXP_TRACE(...) // TRACEARGS(__VA_ARGS__)
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
@ -22,6 +24,7 @@
|
||||
#include "app/site.h"
|
||||
#include "app/util/cel_ops.h"
|
||||
#include "app/util/range_utils.h"
|
||||
#include "base/debug.h"
|
||||
#include "doc/algorithm/shrink_bounds.h"
|
||||
#include "doc/cel.h"
|
||||
#include "doc/image.h"
|
||||
@ -33,11 +36,11 @@
|
||||
#include "doc/tileset.h"
|
||||
#include "doc/tileset_hash_table.h"
|
||||
#include "doc/tilesets.h"
|
||||
#include "gfx/point_io.h"
|
||||
#include "gfx/rect_io.h"
|
||||
#include "gfx/size_io.h"
|
||||
#include "render/render.h"
|
||||
|
||||
#define EXP_TRACE(...) // TRACEARGS
|
||||
|
||||
namespace {
|
||||
|
||||
// We cannot have two ExpandCelCanvas instances at the same time
|
||||
@ -129,13 +132,28 @@ ExpandCelCanvas::ExpandCelCanvas(
|
||||
}
|
||||
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
m_bounds = site.grid().canvasToTile(m_bounds);
|
||||
// Bounds of the canvas in tiles.
|
||||
m_bounds = m_grid.canvasToTile(m_bounds);
|
||||
|
||||
// As the grid origin depends on the current cel position (see
|
||||
// Site::grid()), and we're going to modify the m_cel position
|
||||
// temporarily, we need to adjust the grid to the new temporal
|
||||
// grid origin matching the new m_dstImage position.
|
||||
auto newCelPosition = m_grid.tileToCanvas(m_bounds.origin());
|
||||
m_grid.origin(m_grid.origin() - m_cel->position() + newCelPosition);
|
||||
|
||||
// The origin of m_bounds must be in canvas position
|
||||
m_bounds.setOrigin(newCelPosition);
|
||||
}
|
||||
|
||||
// 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).
|
||||
m_cel->setPosition(m_bounds.x, m_bounds.y);
|
||||
m_cel->setPosition(m_bounds.origin());
|
||||
EXP_TRACE("ExpandCelCanvas",
|
||||
"m_cel->bounds()=", m_cel->bounds(),
|
||||
"m_bounds=", m_bounds,
|
||||
"m_grid=", m_grid.origin(), m_grid.tileSize());
|
||||
|
||||
if (m_celCreated) {
|
||||
getDestCanvas();
|
||||
@ -144,6 +162,13 @@ ExpandCelCanvas::ExpandCelCanvas(
|
||||
if (m_layer && m_layer->isImage())
|
||||
static_cast<LayerImage*>(m_layer)->addCel(m_cel);
|
||||
}
|
||||
else if (m_layer->isTilemap() &&
|
||||
m_tilemapMode == TilemapMode::Tiles) {
|
||||
// Calling "getDestCanvas()" we create the m_dstImage
|
||||
getDestCanvas();
|
||||
m_dstImage->clear(tile_i_notile);
|
||||
m_cel->data()->setImage(m_dstImage, m_layer);
|
||||
}
|
||||
// If we are in a tilemap, we use m_dstImage to draw pixels (instead
|
||||
// of the tilemap image).
|
||||
else if (m_layer->isTilemap() &&
|
||||
@ -234,8 +259,7 @@ void ExpandCelCanvas::commit()
|
||||
m_cel->setPosition(m_origCelPos);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (m_layer->isTilemap() &&
|
||||
m_tilemapMode == TilemapMode::Pixels) {
|
||||
if (m_layer->isTilemap()) {
|
||||
ASSERT(m_cel->image() != m_celImage.get());
|
||||
}
|
||||
else {
|
||||
@ -292,9 +316,10 @@ void ExpandCelCanvas::commit()
|
||||
// Check that the region to copy or patch is not empty before we
|
||||
// create the new cmd
|
||||
else if (!regionToPatch->isEmpty()) {
|
||||
ASSERT(m_celImage.get() == m_cel->image());
|
||||
|
||||
if (m_layer->isBackground()) {
|
||||
// TODO support for tilemap backgrounds?
|
||||
ASSERT(m_celImage.get() == m_cel->image());
|
||||
|
||||
m_cmds->executeAndAdd(
|
||||
new cmd::CopyRegion(
|
||||
m_cel->image(),
|
||||
@ -302,7 +327,24 @@ void ExpandCelCanvas::commit()
|
||||
*regionToPatch,
|
||||
m_bounds.origin()));
|
||||
}
|
||||
else if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
ASSERT(m_celImage.get() != m_cel->image());
|
||||
|
||||
m_cel->data()->setImage(m_celImage, m_layer);
|
||||
gfx::Region regionInCanvas = m_grid.tileToCanvas(*regionToPatch);
|
||||
|
||||
EXP_TRACE(" - Tilemap bounds to patch", regionInCanvas.bounds());
|
||||
|
||||
m_cmds->executeAndAdd(
|
||||
new cmd::PatchCel(
|
||||
m_cel,
|
||||
m_dstImage.get(),
|
||||
regionInCanvas,
|
||||
m_grid.origin()));
|
||||
}
|
||||
else {
|
||||
ASSERT(m_celImage.get() == m_cel->image());
|
||||
|
||||
m_cmds->executeAndAdd(
|
||||
new cmd::PatchCel(
|
||||
m_cel,
|
||||
@ -311,6 +353,11 @@ void ExpandCelCanvas::commit()
|
||||
m_bounds.origin()));
|
||||
}
|
||||
}
|
||||
// Restore the original cel image if needed (e.g. no region to
|
||||
// patch on a tilemap)
|
||||
else if (m_celImage.get() != m_cel->image()) {
|
||||
m_cel->data()->setImage(m_celImage, m_layer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(false);
|
||||
@ -349,13 +396,19 @@ Image* ExpandCelCanvas::getSourceCanvas()
|
||||
ASSERT((m_flags & NeedsSource) == NeedsSource);
|
||||
|
||||
if (!m_srcImage) {
|
||||
m_srcImage.reset(
|
||||
Image::create(m_tilemapMode == TilemapMode::Tiles ? IMAGE_TILEMAP:
|
||||
m_sprite->pixelFormat(),
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
m_srcImage.reset(Image::create(IMAGE_TILEMAP,
|
||||
m_bounds.w, m_bounds.h, src_buffer));
|
||||
m_srcImage->setMaskColor(tile_i_notile);
|
||||
m_srcImage->clear(tile_i_notile);
|
||||
}
|
||||
else {
|
||||
m_srcImage.reset(
|
||||
Image::create(m_sprite->pixelFormat(),
|
||||
m_bounds.w, m_bounds.h, src_buffer));
|
||||
|
||||
m_srcImage->setMaskColor(m_sprite->transparentColor());
|
||||
m_srcImage->clear(m_sprite->transparentColor());
|
||||
m_srcImage->setMaskColor(m_sprite->transparentColor());
|
||||
m_srcImage->clear(m_sprite->transparentColor());
|
||||
}
|
||||
}
|
||||
return m_srcImage.get();
|
||||
}
|
||||
@ -363,12 +416,16 @@ Image* ExpandCelCanvas::getSourceCanvas()
|
||||
Image* ExpandCelCanvas::getDestCanvas()
|
||||
{
|
||||
if (!m_dstImage) {
|
||||
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());
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
m_dstImage.reset(Image::create(IMAGE_TILEMAP,
|
||||
m_bounds.w, m_bounds.h, dst_buffer));
|
||||
m_dstImage->setMaskColor(tile_i_notile);
|
||||
}
|
||||
else {
|
||||
m_dstImage.reset(Image::create(m_sprite->pixelFormat(),
|
||||
m_bounds.w, m_bounds.h, dst_buffer));
|
||||
m_dstImage->setMaskColor(m_sprite->transparentColor());
|
||||
}
|
||||
}
|
||||
return m_dstImage.get();
|
||||
}
|
||||
@ -380,16 +437,21 @@ void ExpandCelCanvas::validateSourceCanvas(const gfx::Region& rgn)
|
||||
getSourceCanvas();
|
||||
|
||||
gfx::Region rgnToValidate;
|
||||
gfx::Point origCelPos;
|
||||
gfx::Point zeroPos;
|
||||
if (m_tilemapMode == TilemapMode::Tiles) {
|
||||
for (const auto& rc : rgn)
|
||||
rgnToValidate |= gfx::Region(m_grid.canvasToTile(rc));
|
||||
// Position of the tilemap cel inside the m_dstImage tilemap
|
||||
origCelPos = m_grid.canvasToTile(m_origCelPos);
|
||||
rgnToValidate = m_grid.canvasToTile(rgn);
|
||||
}
|
||||
else {
|
||||
origCelPos = m_origCelPos;
|
||||
rgnToValidate = rgn;
|
||||
zeroPos = -m_bounds.origin();
|
||||
}
|
||||
EXP_TRACE(" ->", rgnToValidate.bounds());
|
||||
|
||||
rgnToValidate.offset(-m_bounds.origin());
|
||||
rgnToValidate.offset(zeroPos);
|
||||
rgnToValidate.createSubtraction(rgnToValidate, m_validSrcRegion);
|
||||
rgnToValidate.createIntersection(rgnToValidate, gfx::Region(m_srcImage->bounds()));
|
||||
|
||||
@ -398,8 +460,8 @@ void ExpandCelCanvas::validateSourceCanvas(const gfx::Region& rgn)
|
||||
rgnToClear.createSubtraction(
|
||||
rgnToValidate,
|
||||
gfx::Region(m_celImage->bounds()
|
||||
.offset(m_origCelPos)
|
||||
.offset(-m_bounds.origin())));
|
||||
.offset(origCelPos)
|
||||
.offset(zeroPos)));
|
||||
for (const auto& rc : rgnToClear)
|
||||
fill_rect(m_srcImage.get(), rc, m_srcImage->maskColor());
|
||||
|
||||
@ -419,11 +481,24 @@ void ExpandCelCanvas::validateSourceCanvas(const gfx::Region& rgn)
|
||||
m_sprite->palette(m_frame),
|
||||
gfx::RectF(0, 0, m_bounds.w, m_bounds.h),
|
||||
gfx::Clip(rc.x, rc.y,
|
||||
rc.x+m_bounds.x-m_origCelPos.x,
|
||||
rc.y+m_bounds.y-m_origCelPos.y, rc.w, rc.h),
|
||||
rc.x+m_bounds.x-origCelPos.x,
|
||||
rc.y+m_bounds.y-origCelPos.y, rc.w, rc.h),
|
||||
255, BlendMode::NORMAL);
|
||||
}
|
||||
}
|
||||
else if (m_celImage->pixelFormat() == IMAGE_TILEMAP &&
|
||||
m_srcImage->pixelFormat() == IMAGE_TILEMAP) {
|
||||
ASSERT(m_tilemapMode == TilemapMode::Tiles);
|
||||
|
||||
// We can copy the cel image directly
|
||||
for (const auto& rc : rgnToValidate) {
|
||||
m_srcImage->copy(
|
||||
m_celImage.get(),
|
||||
gfx::Clip(rc.x, rc.y,
|
||||
rc.x-origCelPos.x,
|
||||
rc.y-origCelPos.y, rc.w, rc.h));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(m_celImage->pixelFormat() != IMAGE_TILEMAP ||
|
||||
m_tilemapMode == TilemapMode::Tiles);
|
||||
@ -433,8 +508,8 @@ void ExpandCelCanvas::validateSourceCanvas(const gfx::Region& rgn)
|
||||
m_srcImage->copy(
|
||||
m_celImage.get(),
|
||||
gfx::Clip(rc.x, rc.y,
|
||||
rc.x+m_bounds.x-m_origCelPos.x,
|
||||
rc.y+m_bounds.y-m_origCelPos.y, rc.w, rc.h));
|
||||
rc.x+m_bounds.x-origCelPos.x,
|
||||
rc.y+m_bounds.y-origCelPos.y, rc.w, rc.h));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -475,7 +550,8 @@ void ExpandCelCanvas::validateDestCanvas(const gfx::Region& rgn)
|
||||
}
|
||||
EXP_TRACE(" ->", rgnToValidate.bounds());
|
||||
|
||||
rgnToValidate.offset(-m_bounds.origin());
|
||||
if (m_tilemapMode != TilemapMode::Tiles)
|
||||
rgnToValidate.offset(-m_bounds.origin());
|
||||
rgnToValidate.createSubtraction(rgnToValidate, m_validDstRegion);
|
||||
rgnToValidate.createIntersection(rgnToValidate, gfx::Region(m_dstImage->bounds()));
|
||||
|
||||
|
@ -74,6 +74,7 @@ namespace app {
|
||||
void copyValidDestToSourceCanvas(const gfx::Region& rgn);
|
||||
|
||||
const Cel* getCel() const { return m_cel; }
|
||||
const doc::Grid& getGrid() const { return m_grid; }
|
||||
|
||||
private:
|
||||
gfx::Rect getTrimDstImageBounds() const;
|
||||
|
@ -782,6 +782,8 @@ doc::Cel* AsepriteDecoder::readCelChunk(doc::Sprite* sprite,
|
||||
|
||||
if (w > 0 && h > 0) {
|
||||
doc::ImageRef image(doc::Image::create(doc::IMAGE_TILEMAP, w, h));
|
||||
image->setMaskColor(doc::tile_i_notile);
|
||||
image->clear(doc::tile_i_notile);
|
||||
read_compressed_image(f(), delegate(), image.get(), header, chunk_end);
|
||||
cel.reset(new doc::Cel(frame, image));
|
||||
cel->setPosition(x, y);
|
||||
|
@ -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.
|
||||
@ -15,6 +15,7 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tile.h"
|
||||
|
||||
namespace doc {
|
||||
|
||||
@ -149,7 +150,8 @@ void Cel::fixupImage()
|
||||
{
|
||||
// Change the mask color to the sprite mask color
|
||||
if (m_layer && image()) {
|
||||
image()->setMaskColor(m_layer->sprite()->transparentColor());
|
||||
image()->setMaskColor((image()->pixelFormat() == IMAGE_TILEMAP) ?
|
||||
tile_i_notile : m_layer->sprite()->transparentColor());
|
||||
ASSERT(m_data);
|
||||
m_data->adjustBounds(m_layer);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2020 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -52,6 +52,15 @@ gfx::Rect Grid::tileToCanvas(const gfx::Rect& tileBounds) const
|
||||
return gfx::Rect(pt1, pt2);
|
||||
}
|
||||
|
||||
gfx::Region Grid::tileToCanvas(const gfx::Region& tileRgn)
|
||||
{
|
||||
gfx::Region canvasRgn;
|
||||
for (const gfx::Rect& rc : tileRgn) {
|
||||
canvasRgn |= gfx::Region(tileToCanvas(rc));
|
||||
}
|
||||
return canvasRgn;
|
||||
}
|
||||
|
||||
gfx::Point Grid::canvasToTile(const gfx::Point& canvasPoint) const
|
||||
{
|
||||
ASSERT(m_tileSize.w > 0);
|
||||
@ -107,6 +116,16 @@ gfx::Rect Grid::canvasToTile(const gfx::Rect& canvasBounds) const
|
||||
pt2.y - pt1.y + 1));
|
||||
}
|
||||
|
||||
gfx::Region Grid::canvasToTile(const gfx::Region& canvasRgn)
|
||||
{
|
||||
gfx::Region tilesRgn;
|
||||
for (const gfx::Rect& rc : canvasRgn) {
|
||||
tilesRgn |= gfx::Region(canvasToTile(rc));
|
||||
}
|
||||
return tilesRgn;
|
||||
|
||||
}
|
||||
|
||||
gfx::Size Grid::tilemapSizeToCanvas(const gfx::Size& tilemapSize) const
|
||||
{
|
||||
gfx::Point pt = tileToCanvas(gfx::Point(tilemapSize.w-1,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2020 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -47,10 +47,12 @@ namespace doc {
|
||||
// Converts a tile position into a canvas position
|
||||
gfx::Point tileToCanvas(const gfx::Point& tile) const;
|
||||
gfx::Rect tileToCanvas(const gfx::Rect& tileBounds) const;
|
||||
gfx::Region tileToCanvas(const gfx::Region& tileRgn);
|
||||
|
||||
// Converts a canvas position/rectangle into a tile position
|
||||
gfx::Point canvasToTile(const gfx::Point& canvasPoint) const;
|
||||
gfx::Rect canvasToTile(const gfx::Rect& canvasBounds) const;
|
||||
gfx::Region canvasToTile(const gfx::Region& canvasRgn);
|
||||
|
||||
gfx::Size tilemapSizeToCanvas(const gfx::Size& tilemapSize) const;
|
||||
gfx::Rect tileBoundsInCanvas(const gfx::Point& tile) const;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (c) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -17,6 +17,7 @@
|
||||
#include "doc/palette.h"
|
||||
#include "doc/remap.h"
|
||||
#include "doc/rgbmap.h"
|
||||
#include "doc/tile.h"
|
||||
#include "gfx/region.h"
|
||||
|
||||
#include <stdexcept>
|
||||
@ -426,8 +427,12 @@ void remap_image(Image* image, const Remap& remap)
|
||||
case IMAGE_TILEMAP:
|
||||
transform_image<TilemapTraits>(
|
||||
image, [&remap](color_t c) -> color_t {
|
||||
ASSERT(remap[c] != Remap::kNoMap);
|
||||
return remap[c];
|
||||
if (c == tile_i_notile)
|
||||
return tile_i_notile;
|
||||
else {
|
||||
ASSERT(remap[c] != Remap::kNoMap);
|
||||
return remap[c];
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -1285,18 +1285,20 @@ void Render::renderCel(
|
||||
continue;
|
||||
|
||||
const tile_t t = cel_image->getPixel(u, v);
|
||||
const tile_index i = tile_geti(t);
|
||||
if (t != tile_i_notile) {
|
||||
const tile_index i = tile_geti(t);
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user