mirror of
https://github.com/aseprite/aseprite.git
synced 2024-12-29 18:20:44 +00:00
Fix wrong edges on Brush Preview on Tilemap Mode (fix #4176)
This commit is contained in:
parent
0c7759acf1
commit
e9706f106f
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
// Copyright (C) 2019-2024 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -17,7 +17,6 @@
|
|||||||
#include "app/color.h"
|
#include "app/color.h"
|
||||||
#include "app/color_utils.h"
|
#include "app/color_utils.h"
|
||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
#include "app/site.h"
|
|
||||||
#include "app/snap_to_grid.h"
|
#include "app/snap_to_grid.h"
|
||||||
#include "app/tools/controller.h"
|
#include "app/tools/controller.h"
|
||||||
#include "app/tools/ink.h"
|
#include "app/tools/ink.h"
|
||||||
@ -25,7 +24,6 @@
|
|||||||
#include "app/tools/point_shape.h"
|
#include "app/tools/point_shape.h"
|
||||||
#include "app/tools/tool.h"
|
#include "app/tools/tool.h"
|
||||||
#include "app/tools/tool_loop.h"
|
#include "app/tools/tool_loop.h"
|
||||||
#include "app/ui/color_bar.h"
|
|
||||||
#include "app/ui/context_bar.h"
|
#include "app/ui/context_bar.h"
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
#include "app/ui/editor/tool_loop_impl.h"
|
#include "app/ui/editor/tool_loop_impl.h"
|
||||||
@ -165,11 +163,14 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
|||||||
|
|
||||||
tools::Tool* tool = m_editor->getCurrentEditorTool();
|
tools::Tool* tool = m_editor->getCurrentEditorTool();
|
||||||
const bool isFloodfill = tool->getPointShape(0)->isFloodFill();
|
const bool isFloodfill = tool->getPointShape(0)->isFloodFill();
|
||||||
// TODO add support for "tile-brushes"
|
|
||||||
|
// Get current tilemap mode
|
||||||
|
const TilemapMode tilemapMode = site.tilemapMode();
|
||||||
|
|
||||||
gfx::Rect origBrushBounds =
|
gfx::Rect origBrushBounds =
|
||||||
((isFloodfill && brush->type() != BrushType::kImageBrushType) ||
|
((isFloodfill && brush->type() != BrushType::kImageBrushType) ||
|
||||||
site.tilemapMode() == TilemapMode::Tiles ? gfx::Rect(0, 0, 1, 1)
|
tilemapMode == TilemapMode::Tiles ? gfx::Rect(0, 0, 1, 1)
|
||||||
: brush->bounds());
|
: brush->bounds());
|
||||||
gfx::Rect brushBounds = origBrushBounds;
|
gfx::Rect brushBounds = origBrushBounds;
|
||||||
|
|
||||||
// Cursor in the screen (view)
|
// Cursor in the screen (view)
|
||||||
@ -188,9 +189,6 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
|||||||
// Get the current tool
|
// Get the current tool
|
||||||
tools::Ink* ink = m_editor->getCurrentEditorInk();
|
tools::Ink* ink = m_editor->getCurrentEditorInk();
|
||||||
|
|
||||||
// Get current tilemap mode
|
|
||||||
TilemapMode tilemapMode = ColorBar::instance()->tilemapMode();
|
|
||||||
|
|
||||||
// Setup the cursor type depending on several factors (current tool,
|
// Setup the cursor type depending on several factors (current tool,
|
||||||
// foreground color, layer transparency, brush size, etc.).
|
// foreground color, layer transparency, brush size, etc.).
|
||||||
color_t brush_color = getBrushColor(sprite, layer);
|
color_t brush_color = getBrushColor(sprite, layer);
|
||||||
@ -267,6 +265,12 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For tiles as we show the edges of the tile, we add the crosshair
|
||||||
|
// in the mouse position as a helper.
|
||||||
|
if (m_type & BRUSH_BOUNDARIES &&
|
||||||
|
tilemapMode == TilemapMode::Tiles)
|
||||||
|
m_type |= CROSSHAIR;
|
||||||
|
|
||||||
if (m_type & SELECTION_CROSSHAIR)
|
if (m_type & SELECTION_CROSSHAIR)
|
||||||
showPreview = false;
|
showPreview = false;
|
||||||
|
|
||||||
@ -293,7 +297,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
|||||||
m_type &= ~BRUSH_BOUNDARIES;
|
m_type &= ~BRUSH_BOUNDARIES;
|
||||||
}
|
}
|
||||||
if (m_type & BRUSH_BOUNDARIES)
|
if (m_type & BRUSH_BOUNDARIES)
|
||||||
generateBoundaries();
|
generateBoundaries(site, spritePos);
|
||||||
|
|
||||||
// Draw pixel/brush preview
|
// Draw pixel/brush preview
|
||||||
if (showPreview) {
|
if (showPreview) {
|
||||||
@ -321,7 +325,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gfx::Rect extraCelBounds;
|
gfx::Rect extraCelBounds;
|
||||||
if (site.tilemapMode() == TilemapMode::Tiles) {
|
if (tilemapMode == TilemapMode::Tiles) {
|
||||||
ASSERT(layer->isTilemap());
|
ASSERT(layer->isTilemap());
|
||||||
doc::Grid grid = site.grid();
|
doc::Grid grid = site.grid();
|
||||||
extraCelBounds = grid.canvasToTile(extraCelBoundsInCanvas);
|
extraCelBounds = grid.canvasToTile(extraCelBoundsInCanvas);
|
||||||
@ -347,7 +351,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
|||||||
m_extraCel.reset(new ExtraCel);
|
m_extraCel.reset(new ExtraCel);
|
||||||
|
|
||||||
m_extraCel->create(
|
m_extraCel->create(
|
||||||
site.tilemapMode(),
|
tilemapMode,
|
||||||
document->sprite(),
|
document->sprite(),
|
||||||
extraCelBoundsInCanvas,
|
extraCelBoundsInCanvas,
|
||||||
extraCelBounds.size(),
|
extraCelBounds.size(),
|
||||||
@ -432,6 +436,9 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
|||||||
|
|
||||||
if (m_type & NATIVE_CROSSHAIR)
|
if (m_type & NATIVE_CROSSHAIR)
|
||||||
ui::set_mouse_cursor(ui::kCrosshairCursor);
|
ui::set_mouse_cursor(ui::kCrosshairCursor);
|
||||||
|
|
||||||
|
m_lastLayer = site.layer();
|
||||||
|
m_lastTilemapMode = tilemapMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleans the brush cursor from the specified editor.
|
// Cleans the brush cursor from the specified editor.
|
||||||
@ -512,13 +519,38 @@ void BrushPreview::invalidateRegion(const gfx::Region& region)
|
|||||||
m_clippingRegion.createSubtraction(m_clippingRegion, region);
|
m_clippingRegion.createSubtraction(m_clippingRegion, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrushPreview::generateBoundaries()
|
void BrushPreview::calculateTileBoundariesOrigin(const doc::Grid& grid,
|
||||||
|
const gfx::Point& spritePos)
|
||||||
|
{
|
||||||
|
m_brushBoundaries.offset(-m_brushBoundaries.begin()[0].bounds().x,
|
||||||
|
-m_brushBoundaries.begin()[0].bounds().y);
|
||||||
|
gfx::Point canvasPos = grid.tileToCanvas(grid.canvasToTile(spritePos));
|
||||||
|
m_brushBoundaries.offset(canvasPos.x - spritePos.x,
|
||||||
|
canvasPos.y - spritePos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrushPreview::generateBoundaries(const Site& site,
|
||||||
|
const gfx::Point& spritePos)
|
||||||
{
|
{
|
||||||
BrushRef brush = getCurrentBrush();
|
BrushRef brush = getCurrentBrush();
|
||||||
|
Layer* currentLayer = site.layer();
|
||||||
|
TilemapMode tilemapMode = site.tilemapMode();
|
||||||
|
|
||||||
if (!m_brushBoundaries.isEmpty() &&
|
if (tilemapMode == TilemapMode::Pixels &&
|
||||||
m_brushGen == brush->gen())
|
tilemapMode == m_lastTilemapMode &&
|
||||||
|
!m_brushBoundaries.isEmpty() &&
|
||||||
|
m_brushGen == brush->gen()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
else if (tilemapMode == TilemapMode::Tiles &&
|
||||||
|
tilemapMode == m_lastTilemapMode &&
|
||||||
|
m_lastLayer == currentLayer) {
|
||||||
|
// When tilemapMode is 'Tiles' is needed an offset
|
||||||
|
// re-calculation of the brush boundaries, even
|
||||||
|
// if it's no need to update the mask.
|
||||||
|
calculateTileBoundariesOrigin(site.grid(), spritePos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const bool isOnePixel =
|
const bool isOnePixel =
|
||||||
(m_editor->getCurrentEditorTool()->getPointShape(0)->isPixel() ||
|
(m_editor->getCurrentEditorTool()->getPointShape(0)->isPixel() ||
|
||||||
@ -528,7 +560,13 @@ void BrushPreview::generateBoundaries()
|
|||||||
|
|
||||||
Image* mask = nullptr;
|
Image* mask = nullptr;
|
||||||
bool deleteMask = true;
|
bool deleteMask = true;
|
||||||
if (isOnePixel) {
|
if (tilemapMode == TilemapMode::Tiles) {
|
||||||
|
mask = Image::create(IMAGE_BITMAP,
|
||||||
|
site.grid().tileSize().w,
|
||||||
|
site.grid().tileSize().h);
|
||||||
|
mask->clear((color_t)1);
|
||||||
|
}
|
||||||
|
else if (isOnePixel) {
|
||||||
mask = Image::create(IMAGE_BITMAP, 1, 1);
|
mask = Image::create(IMAGE_BITMAP, 1, 1);
|
||||||
mask->putPixel(0, 0, (color_t)1);
|
mask->putPixel(0, 0, (color_t)1);
|
||||||
}
|
}
|
||||||
@ -539,9 +577,13 @@ void BrushPreview::generateBoundaries()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_brushBoundaries.regen(mask ? mask: brushImage);
|
m_brushBoundaries.regen(mask ? mask: brushImage);
|
||||||
if (!isOnePixel)
|
if (tilemapMode == TilemapMode::Pixels) {
|
||||||
m_brushBoundaries.offset(-brush->center().x,
|
if (!isOnePixel)
|
||||||
-brush->center().y);
|
m_brushBoundaries.offset(-brush->center().x,
|
||||||
|
-brush->center().y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
calculateTileBoundariesOrigin(site.grid(), spritePos);
|
||||||
|
|
||||||
if (deleteMask)
|
if (deleteMask)
|
||||||
delete mask;
|
delete mask;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
// Copyright (C) 2019-2024 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2016 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -34,6 +34,7 @@ namespace ui {
|
|||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
class Editor;
|
class Editor;
|
||||||
|
class Site;
|
||||||
|
|
||||||
class BrushPreview {
|
class BrushPreview {
|
||||||
public:
|
public:
|
||||||
@ -90,7 +91,13 @@ namespace app {
|
|||||||
doc::BrushRef getCurrentBrush();
|
doc::BrushRef getCurrentBrush();
|
||||||
static doc::color_t getBrushColor(doc::Sprite* sprite, doc::Layer* layer);
|
static doc::color_t getBrushColor(doc::Sprite* sprite, doc::Layer* layer);
|
||||||
|
|
||||||
void generateBoundaries();
|
// Offset re-calculation of brush boundaries only for TilemapMode::Tiles.
|
||||||
|
// Used within 'generateBoundaries' function.
|
||||||
|
void calculateTileBoundariesOrigin(const doc::Grid& grid,
|
||||||
|
const gfx::Point& spritePos);
|
||||||
|
|
||||||
|
void generateBoundaries(const Site& site,
|
||||||
|
const gfx::Point& spritePos);
|
||||||
|
|
||||||
// Creates a little native cursor to draw the CROSSHAIR
|
// Creates a little native cursor to draw the CROSSHAIR
|
||||||
void createCrosshairCursor(ui::Graphics* g, const gfx::Color cursorColor);
|
void createCrosshairCursor(ui::Graphics* g, const gfx::Color cursorColor);
|
||||||
@ -141,6 +148,9 @@ namespace app {
|
|||||||
gfx::Rect m_lastBounds;
|
gfx::Rect m_lastBounds;
|
||||||
doc::frame_t m_lastFrame;
|
doc::frame_t m_lastFrame;
|
||||||
|
|
||||||
|
doc::Layer* m_lastLayer = nullptr;
|
||||||
|
TilemapMode m_lastTilemapMode;
|
||||||
|
|
||||||
ExtraCelRef m_extraCel;
|
ExtraCelRef m_extraCel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user